弹出窗口如何接收到触摸外部事件的通知?

11
文档说明,当将 setOutsideTouchable(boolean touchable) 设置为 true 时,PopupWindow 将会被通知其窗口外的触摸事件。 但是我没有看到像 setOnOutsideTouchListener 这样的监听器来接收这些信息。 示例。
PopupWindow popup = new PopupWindow();
popup.setOutsideTouchable(true);
//now what..how to receive those touch outside events?

谢谢。

5个回答

16

尝试使用以下代码片段中的setTouchInterceptor:

popup.setTouchInterceptor(new OnTouchListener() 
    {

        public boolean onTouch(View v, MotionEvent event) 
        {
            if (event.getAction() == MotionEvent.ACTION_OUTSIDE) 
            {
                popup.dismiss();
                return true;
            }

            return false;
        }
    });

还要别忘了设置以下标志:

popup.setOutsideTouchable(true);

此外,show..方法(showAtLocation或ShowAsDropDown)应在上述答案之后调用,而不应在其中间调用。 - Thupten
2
如果 (event.getAction() == MotionEvent.ACTION_OUTSIDE) 总是不成立,因为每次都是 MotionEvent.ACTION_DOWN,因此这个解决方案不起作用,更好的解决方案是设置 OnDismissListener,它将在每次单击窗口外部时被调用。我已经将其添加为答案。 - Siddarth G

5

当您触摸 PopupWindow 外部时,默认情况下触摸外部会关闭窗口,从而触发 OnDismissListener。因此,您可以在 popupWindow 上设置 OnDismissListener 来监听窗口外部的触摸事件。

popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
    @Override
    public void onDismiss() {
         //Do Something here
    }
});

比其他答案简单得多。谢谢! - Anubhav Dinkar

0

PopupWindow在处理外部触摸事件时与处理其他所有触摸事件的方式相同。当标志位被设置时,外部事件将被路由到弹出窗口中,您可以像处理触摸事件一样处理它们。没有特殊的方法来测试这个外部事件或设置监听器以处理此类事件。如果您检查源代码:

1341        @Override
1342        public boolean dispatchTouchEvent(MotionEvent ev) {
1343            if (mTouchInterceptor != null && mTouchInterceptor.onTouch(this, ev)) {
1344                return true;
1345            }
1346            return super.dispatchTouchEvent(ev);
1347        }
1348
1349        @Override
1350        public boolean onTouchEvent(MotionEvent event) {
1351            final int x = (int) event.getX();
1352            final int y = (int) event.getY();
1353            
1354            if ((event.getAction() == MotionEvent.ACTION_DOWN)
1355                    && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
1356                dismiss();
1357                return true;
1358            } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
1359                dismiss();
1360                return true;
1361            } else {
1362                return super.onTouchEvent(event);
1363            }
1364        }

现在你可以看到PopupWindow本身会检查事件的X/Y是否在外部并自动关闭。因此,你可以设置TouchInterceptor来捕获事件,而不是使用默认处理程序。或者你可以重写onTouchEvent来处理自己的事件,并在必要时调用super。

0
"弹出窗口是一个浮动容器,出现在当前活动的顶部。"
See: https://developer.android.com/reference/android/widget/PopupWindow.html

我想这就是你要找的。


我知道弹出窗口是什么。我的问题具体涉及setOutsideTouchable方法。 - Thupten
@Thupten 我其实不确定它是如何通知的,但我找到了这个。“控制弹出窗口是否会被通知其窗口外的触摸事件。这仅对可触摸但无法聚焦的弹出窗口有意义,这意味着窗口外的触摸将传递到后面的窗口。默认值为false。如果弹出窗口正在显示,则调用此方法只会在下一次弹出窗口时生效,或通过手动调用其中一个update()方法来生效。”希望这能帮到你。 - user4157770

0

补充:

在我的情况下,如果我在弹出窗口之外点击EditText, 如果设置了setFocusable(true),event.getAction()==0(因此我必须双击EditText才能输入)。 如果设置了setFocusable(false),event.getAction()==4(MotionEvent.ACTION_OUTSIDE)。(单击一次,我就可以输入)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接