Java 点击外部Android对话框以关闭它?

Java 点击外部Android对话框以关闭它?,java,android,dialog,themes,android-3.0-honeycomb,Java,Android,Dialog,Themes,Android 3.0 Honeycomb,我想知道是否有可能在弹出对话框(或带有对话框主题的活动)外点击,然后通过点击对话框外的内容将其关闭 我快速画了一幅图来说明这一点: 正常情况下,您必须按back键关闭对话框,但在蜂巢上,由于所有屏幕状态,您可以选择只在对话框外点击。当您触摸弹出窗口的外侧时,将调用一个触摸拦截器方法 比如说 mWindow.setTouchInterceptor(new OnTouchListener() { @Override public boolean on

我想知道是否有可能在弹出对话框(或带有对话框主题的活动)外点击,然后通过点击对话框外的内容将其关闭

我快速画了一幅图来说明这一点:


正常情况下,您必须按back键关闭对话框,但在蜂巢上,由于所有屏幕状态,您可以选择只在对话框外点击。当您触摸弹出窗口的外侧时,将调用一个
触摸拦截器
方法

比如说

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

                    return true;
                }

                return false;
            }
        });
mWindows
是弹出窗口

如果您希望活动具有相同的功能,则必须遵循以下步骤

1) 在
onCreate()中调用的
setContentView()方法之前添加标志

2) 重写活动中的事件

然后写下面的代码

 @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>

我的应用程序是一个带有Theme.Holo.Dialog的单一活动。在我的情况下,另一个答案不起作用。它只让其他后台应用程序或启动屏幕接收触摸事件

我发现在我的案例中使用它是有效的。我认为这也是一个更简单的解决方案。下面是一些示例代码,介绍如何使用它检测带有对话框主题的活动外的点击:

@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);
}
设置在窗口边界外触摸时是否取消此对话框。

如果对话框是
活动,也可以使用。这一定是
活动的最短路径
s;)


(虽然是API 11+。但API是一个老问题,但又是另一个解决方案:

  • 使您的前台活动全屏显示。使用嵌套布局:全屏布局应具有透明背景(例如
    @null
    @android:color/transparent
    )。内部布局应具有可见背景

  • 在不可见的外部布局中添加一个
    OnClickListener
    ,该布局将
    finish()
    隐藏您的活动


  • 对话框中的任何视图都可以设置为使用触摸事件,这样就不会调用下面的内容

    onCreate(){
        getWindow().getDecorView().getRootView().setOnTouchListener(new OnTouchListener(){
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                dialog.dismiss();
                return false;
            }
        });
    

    我添加了这个,它在3.0以上版本上运行得非常完美,但应该可以在所有版本上运行。

    使用对话框样式,而不是其他样式

    例如,使用

    public YourCustomDialog(Context context) {
        super(context, android.R.style.Theme_Holo_dialog_NoActionBar);
    }
    
    当您使用其他样式时,如主题\u半透明\u NoTitleBar,对话框将不会被关闭。

    您可以使用

      dialog.setCancelable(true\false); 
    
    最新的安卓手机

    它将禁用外部触摸事件

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

    我只需编写对话框。setCanceledOnTouchOut(false);它对我有效,窗口不会在外部点击时关闭。

    this.setFinishOnTouchOut(false)


    你可以使用这个

    这只适用于
    PopupWindow
    ,对吗?我在蜂巢中使用了一个带有Theme.Holo.Dialog主题的标准活动。是的,我在你编写它之前就尝试过了,但也不起作用:(finish上缺少分号()顺便说一句:)使用Theme.Holo.Dialog?记住,这是蜂巢。如果你想在小屏幕上进行测试,只需将活动主题设置为Dialog并单击对话框外部,它就会给你消息。是的,这是可行的-但我不希望后台活动接收触摸事件。我在后台活动中有一些按钮不应该被触发。我想我可以我不能在启动弹出意图时禁用它,但如果有更简单的方法,我肯定更喜欢。如果将if条件更改为
    if(!dialogBounds.contains((int)event.getX(),(int)event.getY())和&event.getAction()==MotionEvent.ACTION\u DOWN),效果会更好
    这样,如果用户不小心将手指移出
    活动,它不会关闭。使用API级别8,使用主题为
    android:theme.Dialog
    的活动,并使用此代码:
    dialogBounds.top
    dialogBounds.left
    的值为0;和
    dialogBounds.bottom
    dialogBounds.right
    具有屏幕大小的值,这表明diolog窗口实际上被假定为全屏。因此我无法将此代码用于工作。还有其他想法说明为什么会发生这种情况吗?这是最好的解决方案…如此简单。为什么这不是答案?我需要它来处理带有对话框主题的活动,而这在这种情况下不起作用案例,但我把它投给了普通对话框。
    this.setFinishOnTouchOut(false);
    适用于对话框活动在
    AlertDialog.Builder
    中没有这样的方法,我不高兴。@Pang for
    AlertDialog.Builder
    try
    alertBox.setCancelable(false);
    除了KITKAT:)它对所有版本都进行了测试。)我相信dismissable是默认行为-至少对于具有对话主题的活动来说是这样。这是一个成功的答案,问题是将活动主题设置为对话,而不是对话框。对于dismissable,请使用
    true
    值:
    This.setFinishOnTouchOut(true)对话框活动需要此方法,但纯对话框不需要此方法。
    
      dialog.setCancelable(true\false); 
    
        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);