Нажмите за пределами диалогового окна Android, чтобы закрыть его? - PullRequest
37 голосов
/ 27 августа 2011

Мне было интересно, можно ли как-то коснуться вне всплывающего диалога (или Действия с темой диалога), и отклонить его, просто нажав за его пределы?

Я сделал короткую картинку, чтобы проиллюстрировать это:

enter image description here

Обычно вы должны нажимать клавишу возврата, чтобы закрыть диалоговые окна, но в Honeycomb было бы здорово иметь возможность просто нажимать вне диалогового окна, потому чтовсе имущество экрана.

Ответы [ 12 ]

89 голосов
/ 06 декабря 2011
dialog.setCanceledOnTouchOutside(true) 

Устанавливает, отменяется ли это диалоговое окно при касании за пределами окна.

47 голосов
/ 17 октября 2011

Мое приложение - это одно действие с 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);
}
14 голосов
/ 27 августа 2011

Существует метод 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) Добавить флаг перед setContentView() вызванным методом 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) Переопределить 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>
5 голосов
/ 28 ноября 2013

Вы можете использовать

  dialog.setCancelable(true\false); 

Для последних версий Android;

Это отключит событие outSideTouching.

5 голосов
/ 20 марта 2012

Вы также можете использовать Activity # setFinishOnTouchOutside , если ваш диалог Activity.Это должен быть кратчайший путь для Activity с;)

(хотя это API 11+. Но API <= 10 обычно имеет нормальный размер экрана.) </p>

4 голосов
/ 24 февраля 2015

Просто пишу dialog.setCanceledOnTouchOutside (false);и это работает для меня, окно не будет отклоняться при внешнем нажатии.

3 голосов
/ 12 января 2015
    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);
1 голос
/ 14 мая 2015

this.setFinishOnTouchOutside (false);

вы можете использовать это

1 голос
/ 25 июля 2013

Используйте стиль диалога, а не другие стили.

Например, используйте

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

При использовании других стилей, таких как Theme_Translucent_NoTitleBar , диалоговое окно не будетуволен.

1 голос
/ 29 мая 2012

Старый вопрос, но еще одно решение:

  1. Сделайте свою переднюю деятельность полноэкранной. Неиспользуемые макеты: Полноэкранный макет должен иметь прозрачный фон (например, @null или @android:color/transparent). Внутренний макет должен иметь видимый фон.

  2. Добавьте OnClickListener к невидимому внешнему макету, который finish() определяет вашу деятельность.

...