在某些Android版本中,当弹出窗口不可调焦时,PopupWindow里面的ListView没有收到触摸事件?

时间:2016-08-08 17:32:56

标签: android listview focus android-popupwindow

好的,我有以下要求:

  • 一个EditText,其中如果用户输入@带有建议的弹出窗口
  • 用户可以继续键入以过滤建议
  • 用户可以点击将完成输入并关闭弹出窗口的建议
  • 用户可以在弹出窗口外点击以解除它

这是我的代码:

        PopupWindow popupWindow = new PopupWindow(mContext);

        // Create ListView to show the suggestions
        ListView listView = new ListView(mContext);
        listView.setBackgroundColor(Color.WHITE);
        MentionsAdapter adapter = new MentionsAdapter(mContext, suggestions);
        listView.setAdapter(adapter);
        listView.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();
            }
        });
        mSuggestionsListView = listView;

        popupWindow.setContentView(listView);
        popupWindow.setFocusable(false);
        popupWindow.setTouchable(true);
        popupWindow.setOutsideTouchable(true);

        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {

            @Override
            public void onDismiss() {
                clearPopupData();
            }
        });

        Rect popupRect = calculatePopupPosition();
        popupWindow.setWidth(popupRect.width());
        popupWindow.setHeight(popupRect.height());
        popupWindow.showAtLocation(mEditor, Gravity.START | Gravity.TOP, popupRect.left, popupRect.top);

        mPopupWindow = popupWindow;

确实有效!问题是它只适用于某些Android版本/设备。例如,它可以在模拟器上的Android 6.0上运行,但它不能在我的同事的LG G4 6.0上运行。它不适用于Android 4.3.1,但适用于4.4.2。 如果PopupWindow无法调焦,则不会调用ListView&#39; s OnItemClickListener。如果PopupWindow可调焦,则会调用ListView OnItemClickListener,但EditText不会收到键盘事件。 我尝试了在PopupWindowListView上更改焦点/触摸模式的无数组合,并且在这些情况下无法使其正常工作。

有关WFT的任何建议正在进行以及如何解决?

2 个答案:

答案 0 :(得分:1)

我找到了实现我想要的方法。因为对于为什么会发生这种不一致的行为,这不仅仅是一种黑客而非真实的答案,我不会接受它作为答案。不过,对于希望达到相同要求的人来说,这可能是有价值的。

我所做的就是投降并让PopupWindow专注,以使其嵌入式ListView能够接收触摸事件:

popupWindow.setFocusable(true);

由于这有效地使ListView也成为键盘事件的接收者,我创建了一个OnKeyListener,将事件转发给EditText:

        listView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                mEditor.dispatchKeyEvent(event);
                return false;
            }
        });

对于清除,这里是问题的完整修改代码:

        PopupWindow popupWindow = new PopupWindow(mContext);

        // Create ListView to show the suggestions
        ListView listView = new ListView(mContext);
        listView.setBackgroundColor(Color.WHITE);
        listView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                mEditor.dispatchKeyEvent(event);
                return false;
            }
        });
        MentionsAdapter adapter = new MentionsAdapter(mContext, suggestions);
        listView.setAdapter(adapter);
        listView.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();
            }
        });
        mSuggestionsListView = listView;

        popupWindow.setContentView(listView);
        popupWindow.setFocusable(true);
        popupWindow.setTouchable(true);
        popupWindow.setOutsideTouchable(true);

        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {

            @Override
            public void onDismiss() {
                clearPopupData();
            }
        });

        Rect popupRect = calculatePopupPosition();
        popupWindow.setWidth(popupRect.width());
        popupWindow.setHeight(popupRect.height());
        popupWindow.showAtLocation(mEditor, Gravity.START | Gravity.TOP, popupRect.left, popupRect.top);

这似乎适用于所有Android版本/设备。如果不希望ListView中的项目进行视觉聚焦,您可以将ListView项目的背景设置为在聚焦时不会改变的颜色或绘图。

答案 1 :(得分:0)

我通过在OnClickListener上设置convertview解决了这个问题,这是适配器的getView方法的参数。然后我调用listview的onItemClickListener的onItemClick方法。

无需使popupWindow可关注事实上,只使用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);

MentionsAdapter getView方法

@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;
    }