He implementado un diálogo personalizado para mi aplicación. Quiero implementar eso cuando el usuario hace clic fuera del cuadro de diálogo, el cuadro de diálogo se cerrará. ¿Qué tengo que hacer para esto?
He implementado un diálogo personalizado para mi aplicación. Quiero implementar eso cuando el usuario hace clic fuera del cuadro de diálogo, el cuadro de diálogo se cerrará. ¿Qué tengo que hacer para esto?
Respuestas:
Puede usar dialog.setCanceledOnTouchOutside(true);
cual cerrará el cuadro de diálogo si toca fuera del cuadro de diálogo.
Algo como,
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
O si su cuadro de diálogo no es modelo, entonces,
1 - Establezca la bandera FLAG_NOT_TOUCH_MODAL
para el atributo de ventana de diálogo
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
2 - Agregue otra bandera a las propiedades de Windows, FLAG_WATCH_OUTSIDE_TOUCH
- esta es para que el diálogo reciba un evento táctil fuera de su región visible.
3 - Anular el onTouchEvent()
diálogo y verificar el tipo de acción. si el tipo de acción es ' MotionEvent.ACTION_OUTSIDE
' significa, el usuario está interactuando fuera de la región de diálogo. Entonces, en este caso, puede oscurecer su diálogo o decidir qué desea realizar. ver plano?
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
System.out.println("TOuch outside the dialog ******************** ");
this.dismiss();
}
return false;
}
Para obtener más información, consulte ¿Cómo descartar un cuadro de diálogo personalizado basado en puntos de contacto? y Cómo descartar su diálogo no modal, cuando se toca fuera de la región del diálogo
Simplemente use
dialog.setCanceledOnTouchOutside(true);
Puede usar esta implementación de onTouchEvent. Impide reaccionar debajo de la actividad al evento táctil (como se mencionó howettl).
@Override
public boolean onTouchEvent ( MotionEvent event ) {
// I only care if the event is an UP action
if ( event.getAction () == MotionEvent.ACTION_UP ) {
// create a rect for storing the window rect
Rect r = new Rect ( 0, 0, 0, 0 );
// retrieve the windows rect
this.getWindow ().getDecorView ().getHitRect ( r );
// check if the event position is inside the window rect
boolean intersects = r.contains ( (int) event.getX (), (int) event.getY () );
// if the event is not inside then we can close the activity
if ( !intersects ) {
// close the activity
this.finish ();
// notify that we consumed this event
return true;
}
}
// let the system handle the event
return super.onTouchEvent ( event );
}
Fuente: http://blog.twimager.com/2010/08/closing-activity-by-touching-outside.html
O, si está personalizando el cuadro de diálogo utilizando un tema definido en su estilo xml, ponga esta línea en su tema:
<item name="android:windowCloseOnTouchOutside">true</item>
dialog.setCanceledOnTouchOutside(true);
funciona maravillosamente
Este método debería evitar por completo las actividades debajo del área gris recuperando eventos de clic.
Elimine esta línea si la tiene:
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
Pon esto en tu actividad creada
getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
luego anule el evento táctil con esto
@Override
public boolean onTouchEvent(MotionEvent ev)
{
if(MotionEvent.ACTION_DOWN == ev.getAction())
{
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
// You have clicked the grey area
displayYourDialog();
return false; // stop activity closing
}
}
// Touch events inside are fine.
return super.onTouchEvent(ev);
}
Este código se usa para cuando se hace clic en el cuadro de diálogo que oculta el tiempo de entrada y cuando el usuario hace clic en el lado exterior del cuadro de diálogo ese tiempo, tanto el softinput como el cuadro de diálogo están cerrados.
dialog = new Dialog(act) {
@Override
public boolean onTouchEvent(MotionEvent event) {
// Tap anywhere to close dialog.
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) event.getX(),
(int) event.getY())) {
// You have clicked the grey area
InputMethodManager inputMethodManager = (InputMethodManager) act
.getSystemService(act.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(dialog
.getCurrentFocus().getWindowToken(), 0);
dialog.dismiss();
// stop activity closing
} else {
InputMethodManager inputMethodManager = (InputMethodManager) act
.getSystemService(act.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(dialog
.getCurrentFocus().getWindowToken(), 0);
}
return true;
}
};
Otra solución, este código fue tomado del código fuente de Android Window
. Debe agregar estos dos métodos al código fuente de su diálogo.
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isShowing() && (event.getAction() == MotionEvent.ACTION_DOWN
&& isOutOfBounds(getContext(), event) && getWindow().peekDecorView() != null)) {
hide();
}
return false;
}
private boolean isOutOfBounds(Context context, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
final View decorView = getWindow().getDecorView();
return (x < -slop) || (y < -slop)
|| (x > (decorView.getWidth()+slop))
|| (y > (decorView.getHeight()+slop));
}
Esta solución no tiene este problema:
Esto funciona muy bien, excepto que la actividad debajo también reacciona al evento táctil. ¿Hay alguna forma de prevenir esto? - howettl
Lo siguiente me ha funcionado:
myDialog.setCanceledOnTouchOutside(true);
Aqui esta el codigo
dialog.getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent ev) {
if(MotionEvent.ACTION_DOWN == ev.getAction())
{
Rect dialogBounds = new Rect();
dialog. getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
// You have clicked the grey area
UiUtils.hideKeyboard2(getActivity());
return false; // stop activity closing
}
}
getActivity().dispatchTouchEvent(ev);
return false;
}
});
Prueba este. puedes ocultar el teclado cuando tocas afuera