2015-06-11 1 views
3

В моем приложении для Android у меня есть EditText. Когда фокусируется EditText, отображается PopupWindow, который содержит ListView. Пользователь может продолжить ввод в EditText, когда на экране отображается PopupWindow, и в то же время он/она должен иметь возможность щелкнуть элемент на ListView, чтобы отклонить PopupWindow. (В зависимости от ListView пункт щелкнул, в дополнение к отклоняя PopupWindow что-то еще должно случиться, но это здесь не имеет значения.)Android ListView OnItemClickListener не работает на нефокусируемом PopupWindow

Проблема заключается в том, хотя «продолжают печатать» часть работы, то «щелкните элемент» часть не делает, потому что OnItemClickListener из ListView никогда не вызывается, и я не могу понять, почему.

Вот мой activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#ddd" 
    android:focusableInTouchMode="true" 
    tools:context="com.example.popuptest3.MainActivity" > 

    <EditText 
     android:id="@+id/edtPhone" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:inputType="phone" /> 

</RelativeLayout> 

Мои popup_window.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#fff" > 

    <ListView 
     android:id="@+id/lstItems" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_marginBottom="60dp" /> 

    <Button 
     android:id="@+id/btnDismiss" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     android:text="Dismiss" /> 

</RelativeLayout> 

Мои list_item.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="50dp" > 

    <TextView 
     android:id="@+id/txtItem" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:gravity="center_vertical" 
     android:text="Item Text" 
     android:textAppearance="?android:attr/textAppearanceMedium" /> 

</RelativeLayout> 

В моем MainActivity классе у меня есть следующий код подготовки:

private PopupWindow popup = null; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    prepareControls(); 
} 

private void prepareControls() { 
    final EditText edtPhone = (EditText)findViewById(R.id.edtPhone); 
    edtPhone.setOnFocusChangeListener(new OnFocusChangeListener() { 
     @Override 
     public void onFocusChange(View v, boolean hasFocus) { 
      if (hasFocus) 
       openPopup(edtPhone); 
      else 
       closePopup(); 
     } 
    }); 
} 

То есть, я открываю PopupWindow когда edtPhone получает фокус, и закройте PopupWindow когда edtPhone теряет фокус. Тогда у меня есть:

private void openPopup(View parent) { 
    closePopup(); 

    // Inflate the view of the PopupWindow. 
    LayoutInflater layoutInflater = LayoutInflater.from(this); 
    View view = layoutInflater.inflate(R.layout.popup_window, 
      new LinearLayout(this), false); 
    final Activity activity = this; 

    // Prepare the ListView. 
    ListView lstItems = (ListView)view.findViewById(R.id.lstItems); 
    lstItems.setAdapter(new ListAdapter(this)); 
    lstItems.setOnItemClickListener(new OnItemClickListener() { 
     @Override 
     public void onItemClick(AdapterView<?> parent, View view, 
       int position, long id) { 
      hideKeyboardAndClearFocus(activity); 
     } 
    }); 

    // Prepare the Button. 
    Button btnDismiss = (Button)view.findViewById(R.id.btnDismiss); 
    btnDismiss.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      hideKeyboardAndClearFocus(activity); 
     } 
    }); 

    // Create and show the PopupWindow. 
    popup = new PopupWindow(view, 400, 300, false); 
    popup.showAtLocation(parent, Gravity.LEFT | Gravity.TOP, 0, 60); 
} 

Кнопка btnDismiss не является частью моего плана; Я добавляю его здесь только для демонстрационных целей. Наконец у меня есть:

private void closePopup() { 
    if (popup != null) { 
     popup.dismiss(); 
     popup = null; 
    } 
} 

private static void hideKeyboardAndClearFocus(Activity activity) { 
    InputMethodManager manager = (InputMethodManager)activity. 
      getSystemService(Activity.INPUT_METHOD_SERVICE); 
    manager.hideSoftInputFromWindow(
      activity.getCurrentFocus().getWindowToken(), 0); 
    activity.getWindow().getDecorView().clearFocus(); 
} 

Я думаю, что это не требует объяснений, а ListAdapter класса вполне стандартен, поэтому я его опускаю.

Теперь, когда я нажимаю на edtPhone, он получает фокус, появляется мягкая клавиатура и открывается PopupWindow. Я могу ввести что-то в edtPhone, и когда я нажимаю на btnDismiss, edtPhone теряет фокус, мягкая клавиатура увольняется, а PopupWindow закрывается, как и ожидалось. Но если вместо btnDismiss я нажимаю на элемент на lstItems, ничего не происходит. Использование Log Я вижу, что OnItemClickListener не вызывается. Самое забавное: ListView можно прокручивать, его просто нельзя щелкнуть.

Я знаю this post, но это решение не подходит для моих целей. Если изменить эту строку:

popup = new PopupWindow(view, 400, 300, false); 

на следующее:

popup = new PopupWindow(view, 400, 300, true); 

PopupWindow становится фокусированием и ListView становится интерактивной, хорошо, но я не могу продолжать вводить в edtPhone.На самом деле, если есть другие меры контроля над деятельностью, все они становятся недоступными, как будто PopupWindow является «модальным».

Я также пробовал android:focusable="false", не повезло. И я не делаю автозаполнение, поэтому AutoCompleteTextView не то, что мне нужно.

Так почему же OnItemClickListener не называется неосведомленным PopupWindow? Я что-то делаю неправильно?

ответ

1

установить popupwindow к не-фокусируемого

popupwindow.setFocusable(false); 
popupwindow.setTouchable(true); 
popupwindow.setOutsideTouchable(true); 

расширить ListView и переопределить следующие методы

@Override 
public boolean hasFocus() { 
    return true; 
} 

@Override 
public boolean isFocused() { 
    return true; 
} 

@Override 
public boolean hasWindowFocus() { 
    return true; 
} 

Это как AutoCompleteTextView реализует всплывающее окно для предложений. Если вам нужно выбрать элемент списка с помощью клавиш DPAD или других клавиш навигации, вам необходимо передать ключевые события из EditText в ListView.

+0

Это было довольно давно, и я перешли, так что, боюсь, я не могу подтвердить ваш ответ. Но я понимаю, что вы предлагаете, и я думаю, что вы правы, поэтому я приму это. Спасибо! – ycsun

+0

Да, это просто решило ту же проблему для меня: onItemLongClickListener не получает вызов из ListView внутри popupWindow. –

0

Я решил эту проблему, просто установив OnClickListener на convertview, что является параметром метода адаптера getView. Затем я вызываю метод onItemClick в onItemClickListener списка.

Не нужно делать popupWindow focusable. Infact, только с помощью ListPopupWindow проще, так как его только внутри getView() метод адаптера, который мы добавляем несколько несколько строк кода

ListPopupWindow popupWindow = new ListPopupWindow(mContext); 

    MentionsAdapter adapter = new MentionsAdapter(mContext, suggestions); 
    popupWindow.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() { 
     @Override 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
      String username = mSuggestions.get(position); 
      String mentionCompletion = username.substring(mCurrentQuery.length()).concat(" "); 
      mEditor.getText().insert(mEditor.getSelectionEnd(), mentionCompletion); 
      hideSuggestions(); 
     } 
    }); 
    popupWindow.setAdapter(adapter); 

MentionsAdaptergetView метод

@Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     if(convertView == null){ 
      convertView = LayoutInflater.from(context).inflate(,R.layout.item_user,parent,false); 

     } 
     // this is the key point of workaround 
     convertView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       popupWindow.getListView().getOnItemClickListener() 
       .onItemClick(listView, v, position, getItemId(position)); 
      } 
     }); 
     return convertView; 
    }