Detectar el botón Atrás pero no descartar el diálogo
Tengo un diálogo para un cuadro de diálogo flotante que incluye un teclado especial que aparece cuando un usuario presiona dentro de un campo EditText (el IME normal no se muestra).
Quisiera que el teclado fuera rechazado (visibilidad = GONE) cuando el usuario presiona el botón de la parte posterior (apenas como con un servicio normal de IME) pero el diálogo permanece visible. Sin embargo, no parece haber una manera de hacer esto en la medida de lo que puedo ver de mi lectura bastante amplia sobre SO y en otros lugares.
- Java.lang.IllegalStateException: No se puede realizar esta acción después de onSaveInstanceState con DialogFragment
- Cómo puedo establecer un intervalo de minutos en DialogFragment
- DialogFragment sin FragmentActivity
- Retener el oyente tras la rotación de la pantalla - DialogFragment con DatePicker
- DialogFragment con ListView personalizado
Si configuro el cuadro de diálogo para que no sea cancelable, entonces no se me notifica por onCancel () o onDismiss () porque el cuadro de diálogo no se puede cancelar.
Si establezco el diálogo para ser cancelable entonces me notifican, pero el diálogo se despide.
No puedo adjuntar un onKeyListener al diálogo en el fragmento porque es reemplazado por el sistema para que el fragmento pueda manejar el ciclo de vida del diálogo.
¿Hay alguna manera de hacer esto? ¿O el acceso a la detección de eventos claves ha sido completamente cercado para los propósitos del sistema Fragment?
- Al pasar argumentos Android DialogFragment, onCreateDialog agument paquete es inesperadamente nulo
- AutoCompleteTextView permite sólo las opciones sugeridas
- Appcompact DialogFragment de una sola opción marca de verificación color
- Método onDateChanged no parece funcionar
- CommitAllowingStateLoss en DialogFragment
- Android - DialogFragment con diseño que contiene fragmento
- Cómo ocultar el teclado en pantalla cuando un DialogFragment es cancelado por el evento setCanceledOnTouchOutside
- No ver la interfaz de EditNameDialogListener
La mejor manera y manera más limpia es anular onBackPressed () en el diálogo que creó en onCreateDialog ().
@Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new Dialog(getActivity(), getTheme()){ @Override public void onBackPressed() { //do your stuff } }; }
Tuve el mismo problema que tú y lo he arreglado adjuntando el onKeyListener a la dialogfragment.
En el método onResume()
de la clase que se extienden de DialogFragment poner estos pedazo de código:
getDialog().setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(android.content.DialogInterface dialog, int keyCode,android.view.KeyEvent event) { if ((keyCode == android.view.KeyEvent.KEYCODE_BACK)) { //Hide your keyboard here!!! return true; // pretend we've processed it } else return false; // pass on to be processed as normal } });
Aquí uno de los problemas que puedes encontrar es que este código va a ser ejecutado dos veces: uno cuando el usuario pulsa el botón de atrás y otro cuando salga para presionarlo. En ese caso, tiene que filtrar por evento:
@Override public void onResume() { super.onResume(); getDialog().setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(android.content.DialogInterface dialog, int keyCode, android.view.KeyEvent event) { if ((keyCode == android.view.KeyEvent.KEYCODE_BACK)) { //This is the filter if (event.getAction()!=KeyEvent.ACTION_DOWN) return true; else { //Hide your keyboard here!!!!!! return true; // pretend we've processed it } } else return false; // pass on to be processed as normal } }); }
Como adición a la respuesta de Juan Pedro Martínez, pensé que sería útil aclarar una pregunta específica (una que tenía) al mirar este hilo.
Si desea crear un nuevo DialogFragment y tenerlo para que el usuario solo pueda cancelarlo con el botón de retroceso, lo que elimina los toques de pantalla aleatorios al cancelar el fragmento prematuramente, entonces este es el código que usaría.
En cualquier código que usted llama el DialogFragment usted necesita fijar el ajuste cancelable a falso de modo que NADA desecha el fragmento, no toca la pantalla perdida, el etc.
DialogFragment mDialog= new MyDialogFragment(); mDialog.setCancelable(false); mDialog.show(getFragmentManager(), "dialog");
A continuación, dentro de DialogFragment, en este caso MyDaialogFragment.java, agrega el código de anulación onResume para que el diálogo escuche el botón Atrás. Cuando se presiona, ejecutará la operación dismiss () para cerrar el fragmento.
@Override public void onResume() { super.onResume(); getDialog().setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(android.content.DialogInterface dialog, int keyCode,android.view.KeyEvent event) { if ((keyCode == android.view.KeyEvent.KEYCODE_BACK)) { // To dismiss the fragment when the back-button is pressed. dismiss(); return true; } // Otherwise, do nothing else else return false; } });
Ahora su diálogo será llamado con el "setCancelable" a false, lo que significa que nada (sin clics fuera) puede cancelarlo y cerrarlo, y permitiendo (desde el propio diálogo) sólo el botón de volver a cerrarlo.
Ganbatte!
@Override public Dialog onCreateDialog(Bundle savedInstanceState) { Dialog dialog = new Dialog(getActivity(), getTheme()) { @Override public void onBackPressed() { //your code } }; return dialog; }
Al crear el cuadro de diálogo, anule ambos onBackPressed y onTouchEvent:
final Dialog dialog = new Dialog(activity) { @Override public boolean onTouchEvent(final MotionEvent event) { //note: all touch events that occur here are outside the dialog, yet their type is just touching-down boolean shouldAvoidDismissing = ... ; if (shouldAvoidDismissing) return true; return super.onTouchEvent(event); } @Override public void onBackPressed() { boolean shouldAvoidDismissing = ... ; if (!shouldSwitchToInviteMode) dismiss(); else ... } };