关于android:PopupWindow-在外部单击时关闭

PopupWindow - Dismiss when clicked outside

我的活动上有一个PopupWindow,问题是即使我与活动进行交互(例如,滚动列表),我的PopupWindow仍然显示。 我可以滚动浏览列表,而PopupWindow仍然存在。

我想要实现的是当我在非PopupWindow的屏幕上触摸/滚动/单击/等等时,我想关闭PopupWindow。 就像菜单如何工作一样。 如果您在菜单外单击,该菜单将被关闭。

我已经尝试过setOutsideTouchable(true),但是它不会关闭窗口。 谢谢。


请尝试在PopupWindow上设置setBackgroundDrawable,如果您触摸窗口外部,该窗口应关闭窗口。


我发现,除了WareNinja对已接受的答案的评论外,提供的答案均不适合我,Marcin S.的答案也可能适用。这是对我有用的部分:

1
2
myPopupWindow.setBackgroundDrawable(new BitmapDrawable());
myPopupWindow.setOutsideTouchable(true);

或者:

1
myPopupWindow.setFocusable(true);

不确定差异是什么,但当setModal的modality设置为true时,ListPopupWindow源代码实际上会使用后者,因此至少Android开发人员认为这是可行的方法,而且只有一行。


我遇到了相同的问题,并将其修复为以下代码。这对我来说可以。

1
2
3
4
5
    // Closes the popup window when touch outside.
    mPopupWindow.setOutsideTouchable(true);
    mPopupWindow.setFocusable(true);
    // Removes default background.
    mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

顺便说一句,不要使用不建议使用BitmapDrawable的构造函数,请使用此新的ColorDrawable(android.R.color.transparent)替换默认背景。

玩得开心@。@


我知道已经晚了,但我注意到人们仍然对弹出窗口有疑问。我决定写一个完整的示例,在其中可以通过触摸或单击弹出窗口的外部或仅触摸窗口本身来关闭弹出窗口。为此,创建一个新的PopupWindow类并复制以下代码:

PopupWindow.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class PopupWindow extends android.widget.PopupWindow
{
Context ctx;
Button btnDismiss;
TextView lblText;
View popupView;

public PopupWindow(Context context)
{
    super(context);

    ctx = context;
    popupView = LayoutInflater.from(context).inflate(R.layout.popup, null);
    setContentView(popupView);

    btnDismiss = (Button)popupView.findViewById(R.id.btn_dismiss);
    lblText = (TextView)popupView.findViewById(R.id.text);

    setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
    setWidth(WindowManager.LayoutParams.WRAP_CONTENT);

    // Closes the popup window when touch outside of it - when looses focus
    setOutsideTouchable(true);
    setFocusable(true);

    // Removes default black background
    setBackgroundDrawable(new BitmapDrawable());

    btnDismiss.setOnClickListener(new Button.OnClickListener(){

        @Override
        public void onClick(View v) {


         dismiss();
        }});

    // Closes the popup window when touch it
/*     this.setTouchInterceptor(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {

            if (event.getAction() == MotionEvent.ACTION_MOVE) {
                dismiss();
            }
            return true;
        }
    }); */  
   } // End constructor

   // Attaches the view to its parent anchor-view at position x and y
   public void show(View anchor, int x, int y)
   {
      showAtLocation(anchor, Gravity.CENTER, x, y);
   }
}

现在为弹出窗口创建布局:
popup.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout    
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="1dp"
    android:orientation="vertical"
    android:padding="10dp">

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"  
    android:gravity="center"
    android:padding="5dp"
    android:text="PopupWindow Example"
    android:textColor="#000000"
    android:textSize="17sp"
    android:textStyle="italic" />

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical">

    <Button
        android:id="@+id/btn_dismiss"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Dismiss"
        android:visibility="gone" />

    <TextView
        android:id="@+id/lbl_dismiss"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Touch outside of this box to dismiss"
        android:textColor="#ffffff"
        android:textStyle="bold" />

</FrameLayout>

在您的主要活动中,创建PopupWindow类的实例:

1
2
final PopupWindow popupWindow = new PopupWindow(this);
popupWindow.show(findViewById(R.id.YOUR_MAIN_LAYOUT), 0, -250);

其中YOUR_MAIN_LAYOUT是popupWindow将要弹出的当前活动的布局


感谢@LunaKong的回答和@HourGlass的确认。我不想发表重复的评论,而只是想使其简洁明了。

1
2
3
4
5
6
7
8
// Closes the popup window when touch outside. This method was written informatively in Google's docs.
mPopupWindow.setOutsideTouchable(true);

// Set focus true to prevent a touch event to go to a below view (main layout), which works like a dialog with 'cancel' property => Try it! And you will know what I mean.
mPopupWindow.setFocusable(true);

// Removes default background.
mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

Mttdat。


对于ListPopupWindow,将窗口设置为模态(如图所示)。

1
mListPopupWindow.setModal(true);

这样,在ListPopupWindow之外单击即可将其关闭。


请注意,要使用popupWindow.setOutsideTouchable(true)取消,
您需要使宽度和高度wrap_content像下面的代码所示:

1
2
3
4
5
6
7
8
9
PopupWindow popupWindow = new PopupWindow(
            G.layoutInflater.inflate(R.layout.lay_dialog_support, null, false),
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT, true);

popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
popupWindow.showAtLocation(view, Gravity.RIGHT, 0, 0);

触摸外部时,可以使用isOutsideTouchableisFocusable关闭弹出窗口

1
2
3
popupWindow.isOutsideTouchable = true // dismiss popupwindow when touch outside

popupWindow.isFocusable = true // dismiss popupwindow when touch outside AND when press back button

注意

  • 目前,经过测试,我发现setBackgroundDrawable不能帮助我们关闭popupwindow

  • 如果您查看PopupWindow中的关闭代码(PopupWindow->PopupDecorView->dispatchKeyEventPopupWindow->PopupDecorView->onTouchEvent)。您会看到,按返回按钮时,它们在ACTION_UP上关闭,而在触摸外部时,它们在ACTION_UPACTION_OUTSIDE上关闭


1
2
3
  popupWindow.setTouchable(true);
  popupWindow.setFocusable(true);
  popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);

当在屏幕上单击/触摸时,它将关闭PopupWindow。请确保在showAtLocation之前将focusable设置为true。


@LunaKong建议工作就像一种魅力。

但是设置mPopupWindow.setFocusable(false)。删除使弹出窗口消失所需的不必要的触摸。

例如:
让我们考虑一下屏幕上有一个弹出窗口,您将要单击一个按钮。
因此,在这种情况下,(如果mpopwindow.setFocusable(true))
在第一次单击按钮时,弹出窗口将关闭。
但是您必须再次单击才能使按钮起作用。
如果**(mpopwindwo.setFocusable(false)**
单击按钮即可关闭弹出窗口并触发按钮单击。
希望能帮助到你。


将窗口背景设置为透明:

1
PopupWindow.getBackground().setAlpha(0);

之后,在布局中设置背景。工作良好。


1
mPopWindow.setFocusable(true);


在某些情况下,使弹出窗口具有可聚焦性是不希望的(例如,您可能不希望它从另一个视图中夺取焦点)。

另一种方法是使用触摸拦截器:

1
2
3
4
5
6
7
8
9
10
popupWindow.setOutsideTouchable(true);
popupWindow.setTouchInterceptor(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
            popupWindow.dismiss();
        }
        return false;
    }
});

使用View popupView关闭popupWindow

1
2
3
4
5
6
`popupView.setOnClickListener(new View.OnClickListener() {
                   @Override
                   public void onClick(View view) {
                       popupWindow.dismiss();
                   }
               });

`
如果使用此方法,还可以将onClickClick设置为popupWindow内的任何按钮