2011-08-27 88 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);

你可以使用这个