PopupWindow - 在外部点击时关闭

时间:2012-09-02 01:19:41

标签: android popupwindow android-menu

我的活动中有一个PopupWindow,即使我正在与我的活动进行交互(比如在我的列表上滚动),我的PopupWindow仍会显示。我可以滚动浏览我的列表,PopupWindow仍在那里。

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

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

15 个答案:

答案 0 :(得分:123)

如果您触摸窗外,请尝试设置setBackgroundDrawable PopupWindow关闭窗口。

答案 1 :(得分:112)

我发现除了WareNinja对接受的答案的评论之外,所提供的答案都没有给我工作,而Marcin S.可能也会有效。这是适合我的部分:

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

可替换地:

myPopupWindow.setFocusable(true);

不确定区别是什么,但ListPopupWindow源代码在使用setModal将其模态设置为true时实际使用后者,因此至少Android开发人员认为这是一种可行的方法,而且它只有一行。

答案 2 :(得分:50)

我遇到了同样的问题,并将其修复为以下代码。它对我来说很好。

    // 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) 来替换默认背景。

玩得开心@。@

答案 3 :(得分:21)

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

<强> PopupWindow.class

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

<?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类的实例:

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

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

答案 4 :(得分:10)

感谢@ LunaKong的回答和@ HourGlass的确认。我不想做一个重复的评论,但只想简明扼要。

// 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。

答案 5 :(得分:6)

请注意,对于使用popupWindow.setOutsideTouchable(true)取消,  你需要像下面的代码一样制作宽度和高度wrap_content

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);

答案 6 :(得分:4)

对于ListPopupWindow,在显示时将窗口设置为模态。

mListPopupWindow.setModal(true);

这样,点击ListPopupWindow外部就会将其解雇。

答案 7 :(得分:3)

mPopWindow.setFocusable(true);

答案 8 :(得分:3)

将窗口背景设置为透明:

PopupWindow.getBackground().setAlpha(0);

在布局中设置背景后。工作正常。

答案 9 :(得分:2)

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

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

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

答案 10 :(得分:1)

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

点击/触摸屏幕时会关闭PopupWindow。确保在showAtLocation之前设置了focusable true。

答案 11 :(得分:1)

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

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

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

答案 12 :(得分:1)

如果此弹出窗口是另一个活动,并且您将其大小减小到原始屏幕 并且您要启用或禁用外部区域。您可以通过以下代码简单地启用或禁用外部区域:

启用:

YourActivity.this.setFinishOnTouchOutside(true);

禁用:

YourActivity.this.setFinishOnTouchOutside(false);

答案 13 :(得分:0)

使用View popupView关闭popupWindow

`popupView.setOnClickListener(new View.OnClickListener() {
                   @Override
                   public void onClick(View view) {
                       popupWindow.dismiss();
                   }
               }); 

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

答案 14 :(得分:0)

您可以使用isOutsideTouchable OR isFocusable在外部触摸时关闭弹出窗口

popupWindow.isOutsideTouchable = true // dismiss popupwindow when touch outside

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

注意

  • 目前,经过测试,我看到setBackgroundDrawable 帮助我们关闭弹出窗口

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

  • 上关闭