setpositivebutton prevent don closing close cancel avoid android dialog android-activity touch

don - prevent close dialog android



¿Cómo cancelar una actividad temática de Diálogo como cuando se toca fuera de la ventana? (14)

Encontré una respuesta aún más simple que funcionó perfectamente para mí. Si está utilizando una actividad con el tema del diálogo, puede aplicar this.setFinishOnTouchOutside(true); al método onCreate () de la actividad.

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_yoptions); this.setFinishOnTouchOutside(true); }

Tengo una actividad con un tema de diálogo y me gustaría cerrar (finalizar) esta actividad cuando alguien toca la pantalla en cualquier lugar fuera de la ventana de esta actividad. Cómo puedo hacer esto ?


Es muy simple, solo establece la propiedad canceledOnTouchOutside = true . mira el ejemplo:

Dialog dialog = new Dialog(context) dialog.setCanceledOnTouchOutside(true);


Es posible bastante fácilmente:

Primero defina su propio tema en style.xml:

<style name="DialogSlideAnim" parent="@android:style/Theme.Holo.Dialog"> <item name="android:windowContentOverlay">@null</item> <item name="android:windowCloseOnTouchOutside">true</item> </style>

Luego, en su manifiesto, aplique este tema a la actividad:

<activity android:label="@string/app_name" android:name=".MiniModeActivity" android:theme="@style/DialogSlideAnim" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>


La única forma en que logré que esto funcionara fue

alert = new AlertDialog.Builder(this).... alert.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(final DialogInterface arg0) { Log.i(APP_NAME, "in OnDismissListener"); // removeDialog(R.layout.dialog3); alert.dismiss(); finish(); }

es decir, tuve que descartar y terminar de forma explícita; de lo contrario, terminé con un pequeño rectángulo blanco en el medio de la pantalla.


No pude obtener la respuesta principal aquí para trabajar en una pestaña de Samsung con 3.1, así que hice esto:

@Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); int xmargin = (ViewUtils.getScreenWidth() - Constants.PRODUCT_DIALOG_WIDTH) / 2; int ymargin = (ViewUtils.getScreenHeight() - Constants.PRODUCT_DIALOG_HEIGHT) / 2; if ( x < xmargin || x > ViewUtils.getScreenWidth() - xmargin || y < ymargin || y > ViewUtils.getScreenHeight() - ymargin ) { finish(); return true; } return super.onTouchEvent(event); }

Tendrá que reemplazar Constantes.PRODUCT_DIALOG_WIDTH y Constantes.PRODUCT_DIALOG_HEIGHT con el ancho / alto de su cuadro de diálogo. El mío se usó en varios lugares, así que los hice constantes.

También necesitará implementar su propio método para obtener el ancho y el alto de la pantalla, que puede encontrar fácilmente en este sitio. ¡No te olvides de dar cuenta del encabezado de Android en eso!

Es algo feo, y no estoy orgulloso, pero funciona.


Puede hacer referencia al código dialog.java desde la fuente de Android:

public boolean onTouchEvent(MotionEvent event) { if (mCancelable && mCanceledOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { cancel(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth()+slop)) || (y > (decorView.getHeight()+slop)); }

Simplemente modifíquelo a:

public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { finish(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(this).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth() + slop)) || (y > decorView.getHeight() + slop)); }

puede resolver tu problema


Si no hay compatibilidad con API, solo debe usar FrameLayout para llenar la pantalla y crear manualmente una ventana emergente. Luego puede recibir el foco en cualquier lugar de la pantalla y mostrar / ocultar las vistas en consecuencia.


Si usa un tema de diálogo como android:theme="@style/Theme.AppCompat.Dialog" o cualquier otro tema de diálogo. En API 11 y después podemos usar

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { setFinishOnTouchOutside(false); }

llama esto dentro onCreate de la actividad.


Solo agrega este elemento a styles.xml :

<style name="alert_dialog" parent="android:Theme.Dialog"> <item name="android:windowIsFloating">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowNoTitle">true</item> <item name="android:windowFullscreen">false</item> <item name="android:windowBackground">@color/float_transparent</item> <item name="android:windowAnimationStyle">@null</item> <item name="android:backgroundDimEnabled">true</item> <item name="android:backgroundDimAmount">0.4</item> </style>

Y en onCreate() y antes de setContentView :

setTheme(R.style.alert_dialog);


Solo para señalar que hay una forma de obtener un comportamiento de "tocar afuera para cancelar" desde un tema de Actividad como un diálogo, aunque no he investigado completamente si tiene efectos secundarios no deseados.

Dentro del método onCreate () de su actividad, antes de crear la vista, establecerá dos indicadores en la ventana: uno para que sea ''no modal'', para permitir que las vistas que no sean de su actividad reciban eventos. El segundo es recibir notificación de que uno de esos eventos ha tenido lugar, lo que le enviará un evento ACTION_OUTSDIE move.

Si configura el tema de la actividad para el tema del diálogo, obtendrá el comportamiento que desea.

Se ve algo como esto:

public class MyActivity extends Activity { @Override protected 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); // Note that flag changes must happen *before* the content view is set. setContentView(R.layout.my_dialog_view); } @Override public boolean onTouchEvent(MotionEvent event) { // If we''ve received a touch notification that the user has touched // outside the app, finish the activity. if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { finish(); return true; } // Delegate everything else to Activity. return super.onTouchEvent(event); } }


Una actividad tiene el uso de dispatchTouchEvent que

@Override public boolean dispatchTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub finish(); return super.dispatchTouchEvent(ev); }


Una combinación de las respuestas de Gregory y Matt funcionó mejor para mí (para Honeycomb y presumiblemente para otros). De esta forma, las vistas externas no recibirán eventos táctiles cuando el usuario intente tocar-fuera-cancelar el diálogo.

En la Actividad principal, crea el interceptor táctil en onCreate ():

touchInterceptor = new FrameLayout(this); touchInterceptor.setClickable(true); // otherwise clicks will fall through

En onPause () agrégalo:

if (touchInterceptor.getParent() == null) { rootViewGroup.addView(touchInterceptor); }

(rootViewGroup puede tener que ser un FrameLayout o un RelativeLayout. LinearLayout puede no funcionar).

En onResume (), elimínelo:

rootViewGroup.removeView(touchInterceptor);

Luego, para la Actividad con tema de diálogo, use el código que Gregory ofreció (copiado aquí para su conveniencia):

public class MyActivity extends Activity { @Override protected 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); // Note that flag changes must happen *before* the content view is set. setContentView(R.layout.my_dialog_view); } @Override public boolean onTouchEvent(MotionEvent event) { // If we''ve received a touch notification that the user has touched // outside the app, finish the activity. if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { finish(); return true; } // Delegate everything else to Activity. return super.onTouchEvent(event); } }


Usando el método setFinishOnTouchOutside para habilitar / deshabilitar si el exterior es touchable o no.

Esto funciona para la actividad .

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_yoptions); /* your code here */ // set outside touchable this.setFinishOnTouchOutside(true); }


@Override public boolean dispatchTouchEvent(MotionEvent ev) { Rect dialogBounds = new Rect(); getWindow().getDecorView().getHitRect(dialogBounds); if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) { return true; } return super.dispatchTouchEvent(ev); }

Este código está resuelto mi problema.