2011-08-27 90 views
37

我想知道是否有可能以某種方式在彈出對話框(或帶有對話框主題的活動)之外輕敲,並通過輕敲它外面來解除它?點擊Android外部對話框關閉它?

我做了一個快速的圖片來說明吧:

enter image description here

通常情況下,你必須按後退鍵關閉對話框,但在Honeycomb上它可能是有很大的只是敲擊選項在對話之外,由於所有的屏幕屬性。

+1

我相信dismissable是默認行爲 - 至少對於具有Dialog主題的Activity。 –

回答

47

我的應用是Theme.Holo.Dialog單個活動。在我的情況下,其他答案沒有奏效。它只讓其他後臺應用程序或啓動屏幕接收觸摸事件。

我發現使用dispatchTouchEvent適用於我的情況。我認爲這也是一個更簡單的解決方案。下面是關於如何與對話主題,用它來檢測水龍頭的活動之外的一些示例代碼:當窗口的邊界之外觸及此對話框

@Override 
public boolean dispatchTouchEvent(MotionEvent ev) { 
    Rect dialogBounds = new Rect(); 
    getWindow().getDecorView().getHitRect(dialogBounds); 

    if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) { 
     // Tapped outside so we finish the activity 
     this.finish(); 
    } 
    return super.dispatchTouchEvent(ev); 
} 
+12

如果您將if條件更改爲if(!),那麼這會更好。這樣,如果用戶不小心將他們的手指移動到「活動」之外,它就不會關閉。 – Glitch

+0

這真是太棒了,Glitch - 非常感謝。 –

+1

使用API​​級別8,使用主題爲「android:Theme.Dialog」的活動以及此代碼:'dialogBounds.top'和'dialogBounds.left'的值爲0; 'dialogBounds.bottom'和'dialogBounds.right'具有屏幕大小的值,表明實際上diolog窗口假定爲全屏。所以我不能讓這個代碼工作。任何其他想法爲什麼會發生? – Jorge

14

有一個TouchInterceptor方法時,你就出彈出窗口的側碰這將稱爲

例如

mWindow.setTouchInterceptor(new OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { 
        mWindow.dismiss(); 

        return true; 
       } 

       return false; 
      } 
     }); 

mWindow是彈出窗口

如果你想爲相同的功能活動你必須遵循以下步驟。

1)在活動

添加標誌之前調用在onCreate();

getWindow().setFlags(LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_NOT_TOUCH_MODAL); 

    // ...but notify us that it happened. 
    getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); 

2)setContentView()方法重寫onTouchEvent()事件和下面的代碼寫

@Override 
     public boolean onTouchEvent(MotionEvent event) { 
      if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { 
       Toast.makeText(getApplicationContext(), "Finish", 3000).show(); 
       finish();    
       return true; 
      } 
      return false; 
     } 

的完整副本是這裏

活動

package net.londatiga.android; 

import android.app.Activity; 
import android.os.Bundle; 

import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.View.OnTouchListener; 
import android.view.WindowManager.LayoutParams; 

import android.widget.Button; 
import android.widget.Toast; 

public class NewQuickAction3DActivity extends Activity implements OnTouchListener { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     // Make us non-modal, so that others can receive touch events. 
     getWindow().setFlags(LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_NOT_TOUCH_MODAL); 

     // ...but notify us that it happened. 
     getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); 

     setContentView(R.layout.main); 

    } 


    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { 
      Toast.makeText(getApplicationContext(), "Hi", 3000).show(); 

      return true; 
     } 

     return false; 
    } 
} 

這是manifest.xml的

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
     package="net.londatiga.android" 
     android:versionCode="1" 
     android:versionName="1.0"> 
    <uses-sdk android:minSdkVersion="7" /> 

    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
     <activity android:name=".NewQuickAction3DActivity" 
        android:label="@string/app_name" android:theme="@android:style/Theme.Holo.Dialog"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

    </application> 
</manifest> 
+2

這僅適用於'PopupWindow',對吧?我在Honeycomb中使用了Theme.Holo.Dialog主題的標準Activity。 –

+0

我編輯我的答案檢查它 – Dharmendra

+0

是的,我試過它,然後你寫它,但它也沒有工作:(在完成()btw丟失分號:) –

89
dialog.setCanceledOnTouchOutside(true) 

設置是否被取消。

+2

這是最好的解決方案......太簡單了。爲什麼不是這個答案? –

+1

我需要它使用對話框主題處理一個Activity,在這種情況下這不起作用,但我已經將它用於常規對話框。 –

+3

'this.setFinishOnTouchOutside(false);'適用於對話框活動 – Nick

5

如果您的對話框是Activity,您也可以使用Activity#setFinishOnTouchOutside。這是Activity s的最短路徑;)

(雖然它是API 11+,但是API < = 10通常是屏幕大小正常。)

+0

這是獲勝的答案,問題在於將主題定義爲對話框的活動,不是對話框。 – JaredBanyard

1

老問題,但另一種解決方案:

  1. 讓您的前臺活動全屏。 Usenested佈局:全屏佈局應具有透明背景(例如@null@android:color/transparent)。內部佈局應該有可見的背景。

  2. OnClickListener添加到隱藏的外部佈局,finish()您的活動。

0

對話框中的任何視圖都可以設置爲使用觸摸事件,以便不會調用以下內容。

onCreate(){ 
    getWindow().getDecorView().getRootView().setOnTouchListener(new OnTouchListener(){ 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      dialog.dismiss(); 
      return false; 
     } 
    }); 
0
LayoutParams lp=dialogp.getWindow().getAttributes(); 
lp.flags=LayoutParams.FLAG_LAYOUT_NO_LIMITS; 

我說這和它完美的作品在3.0,但應該對所有工作。

1

使用對話框樣式而不是其他樣式。

例如,使用

public YourCustomDialog(Context context) { 
    super(context, android.R.style.Theme_Holo_dialog_NoActionBar); 
} 

當您使用其他樣式像Theme_Translucent_NoTitleBar,對話框將不會被解僱。

5

您可以使用

dialog.setCancelable(true\false); 

對於安卓的最新的vesrions;

它將禁用outSideTouching事件。

+0

哪些版本? – AbleArcher

+0

除KITKAT以外的所有版本均經過測試:) – Amt87

3
dialog = new Dialog(MainActivity.this); 
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 
    dialog.setContentView(R.layout.dialog_layout); 
    dialog.getWindow().setBackgroundDrawableResource(
      android.R.color.transparent); 
    dialog.setCancelable(false); 

    dialog.setCanceledOnTouchOutside(true); 

檢查,如果你有這行代碼或不....

dialog.setCanceledOnTouchOutside(true); 
4

只要我寫dialog.setCanceledOnTouchOutside(假);它適用於我,窗戶不會在外面輕拍。

1

this.setFinishOnTouchOutside(false);

你可以使用這個