Détecter le bouton Retour mais ne pas ignorer le dialog

J’ai un dialog de dialog pour une boîte de dialog flottante qui inclut un clavier spécial qui apparaît lorsqu’un utilisateur appuie sur un champ EditText (l’IME normal n’est plus affiché).

Je voudrais que le clavier soit supprimé (visibility = GONE) lorsque l’utilisateur appuie sur le bouton de retour (comme avec un service IME normal) mais que la boîte de dialog rest visible. Cependant, il ne semble pas y avoir de moyen de le faire pour autant que je puisse le constater en lisant mes lectures assez approfondies sur SO et ailleurs.

Si je mets la boîte de dialog à ne pas pouvoir annuler, je ne suis pas averti par onCancel () ou onDismiss () car la boîte de dialog n’est pas annulable.

Si je mets la boîte de dialog à annuler, je suis averti, mais la boîte de dialog est rejetée.

Je ne peux pas attacher un onKeyListener à la boîte de dialog du fragment car il est remplacé par le système pour que le fragment puisse gérer le cycle de vie de la boîte de dialog.

Est-ce qu’il y a un moyen de faire ça? Ou est-ce que l’access à la détection d’événements clés a été entièrement isolé pour les besoins du système de fragmentation?

Le meilleur moyen est de remplacer onBackPressed () dans la boîte de dialog que vous avez créée dans onCreateDialog ().

@Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new Dialog(getActivity(), getTheme()){ @Override public void onBackPressed() { //do your stuff } }; } 

J’ai eu le même problème que vous et je l’ai corrigé en attachant le onKeyListener au dialog de dialog.

Dans la méthode onResume() de la classe qui s’étend de DialogFragment mettez ces morceaux de code:

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

Ici, l’un des problèmes que vous pouvez trouver est que ce code va être exécuté deux fois: un lorsque l’utilisateur appuie sur le bouton retour et un autre quand il quitte pour appuyer dessus. Dans ce cas, vous devez filtrer par événement:

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

Comme additif à la réponse de Juan Pedro Martinez, j’ai pensé qu’il serait utile de clarifier une question spécifique (celle que j’avais) en regardant ce fil.

Si vous souhaitez créer un nouveau DialogFragment et l’avoir afin que l’utilisateur puisse uniquement l’annuler en utilisant le bouton retour, ce qui élimine les touches d’écran aléatoires de l’annulation prématurée du fragment, alors c’est le code que vous utiliseriez.

Quel que soit le code que vous appelez le DialogFragment, vous devez définir le paramètre peut être annulé sur false afin que NOTHING ne rejette pas le fragment, que l’écran ne touche pas, etc.

 DialogFragment mDialog= new MyDialogFragment(); mDialog.setCancelable(false); mDialog.show(getFragmentManager(), "dialog"); 

Ensuite, dans votre DialogFragment, dans ce cas MyDaialogFragment.java, vous ajoutez le code de substitution onResume pour que la boîte de dialog écoute le bouton Précédent. Quand il est pressé, il exécutera le rejet () pour fermer le fragment.

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

Maintenant, votre boîte de dialog sera appelée avec “setCancelable” à false, ce qui signifie que rien (aucun clic externe) ne pourra l’annuler et l’arrêter, et autoriser (depuis la boîte de dialog elle-même) uniquement le bouton Précédent pour la fermer.

Ganbatte!

Comment personne n’a suggéré cela?

 public Dialog onCreateDialog(Bundle savedInstanceState) { Dialog dialog = super.onCreateDialog(savedInstanceState); // Add back button listener dialog.setOnKeyListener(new Dialog.OnKeyListener() { @Override public boolean onKey(DialogInterface dialogInterface, int keyCode, KeyEvent keyEvent) { // getAction to make sure this doesn't double fire if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.getAction() == KeyEvent.ACTION_UP) { // Your code here return true; // Capture onKey } return false; // Don't capture } }); return dialog; } 

Lors de la création de la boîte de dialog, remplacez à la fois onBackPressed et 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 ... } }; 
 @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Dialog dialog = new Dialog(getActivity(), getTheme()) { @Override public void onBackPressed() { //your code } }; return dialog; }