2012-09-02 117 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。