2012-09-02 219 views
63

我对我的活动有一个PopupWindow,事情是即使当我与我的活动进行交互时(例如在列表中滚动),我的PopupWindow仍然会显示。我可以滚动浏览列表,PopupWindow仍然存在。PopupWindow - 在外部点击时关闭

我想实现的是当我在不是PopupWindow的屏幕上触摸/滚动/点击/等时,我想关闭PopupWindow。就像菜单是如何工作的。如果您在菜单外单击,菜单将被解除。我试过setOutsideTouchable(true),但它不会关闭窗口。谢谢。

回答

106

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

+0

但这不是一个对话框,但它是一个PopupWindow – lorraine

+5

我错过了它。你在你的popupWindow上使用setBackgroundDrawable吗?我知道设置背景drawable为null会杀死OnTouchListener –

+0

你明白了。设置backgroundDrawable的作品。你可能想编辑你的答案,所以我可以将其标记为已接受。 :)感谢朋友。 – lorraine

19

我知道这是晚了,但我注意到人们仍然有弹出窗口的问题。我决定编写一个完整的工作示例,在这个示例中,您可以通过触摸或点击弹出窗口或仅触摸窗口本身来关闭弹出窗口。这样做,创建一个新的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会弹出

+1

谢谢 - 这对我有用。只需要注意的一点是,为您的自定义类使用PopupWindow以外的其他名称,也许将其称为MyPopupWindow而不是Popupwindow,这样android就不会在您的标准android类和自定义类之间产生混淆。 – Simon

+0

@Marcin S. findViewById(R.id.YOUR_MAIN_LAYOUT)??请问是R.layout.My_Layout –

+0

@Simon findViewById(R.id.YOUR_MAIN_LAYOUT)??它会是R.layout.My_Layout? –

91

我发现,没有提供答案的工作对我来说,除了WareNinja的评论上公认的答案, Marcin S.也可能会工作。下面是对我的作品的一部分:

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

或者:

myPopupWindow.setFocusable(true); 

不知道的区别是什么,但ListPopupWindow源代码实际使用后者时,它的模式设置为true与setModal,所以至少Android开发者认为这是一种可行的方法,而且它只是一条线。

+5

非常感谢。没有其他答案为我工作或解释得不错。第二个选项虽然不适合我。 – JDN

+3

第一个解决方案有效,但第二个解决方案实际上不行。 – HAL9000

+2

另外我注意到,BitmapDrawable已被弃用。有一个真正的解决方案将是很好的,因为这些看起来像临时解决方案并不保证在新的API版本中得到支持。 – HAL9000

2
mPopWindow.setFocusable(true); 
3

设置窗口的背景透明:

PopupWindow.getBackground().setAlpha(0); 

后,它设置您的布局的背景。工作正常。

+0

getBackground()可能为空之前添加此代码。 –

4

对于ListPopupWindow将窗口设置为显示模式。

mListPopupWindow.setModal(true); 

这样,点击ListPopupWindow以外的地方就会消除它。

42

我遇到了同样的问题,并将其固定为以下代码。这对我来说可以。

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

BTW,不要使用BitmapDrawable过时的构造函数,使用这个新ColorDrawable(android.R.color.transparent)替换默认背景。

玩得开心@。@

+0

请务必在显示您的popoupWindow –

2

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

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

例如: 让我们考虑一下弹出窗口在屏幕上可见,而您即将点击一个按钮。 所以在这种情况下,(如果mpopwindow.setFocusable(true)) 第一次点击一个按钮popupwindow将会消失。 但是你必须再次点击才能使按钮有效。 如果**(mpopwindwo.setFocusable(假)** 按钮的单次点击关闭该弹出窗口以及触发按钮的点击。 希望它能帮助。

+1

之前添加此代码非常感谢!我正在寻找相同的 – Ganesh

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

它将解雇PopupWindow时点击screen.Make /触摸确保您已设置可聚焦真showAtLocation前

+1

请添加一些说明性文字来阐述这是如何为被问题提供准确答案的。谢谢。 – philantrovert

5

注意与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); 
0

在某些情况下,使弹出式对焦不可取(例如,你可能不希望它从另一个角度窃取焦点)。

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

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

这件事情在棒棒糖版本不行,我试了一下。 –

3

感谢@ LunaKong答案,并@沙漏的确认。我不想做出重复的评论,但只想说清楚和简洁。

// Closes the popup window when touch outside. This method was written informatively in Google's docs. 
mPopupWindow.setOutsideTouchable(true); 

// Set focus true to make prevent touch event to 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。