web-dev-qa-db-fra.com

Détecter le bouton de retour mais ne pas fermer le dialoguefragment

J'ai un dialogfragment pour un dialogue flottant qui inclut un clavier spécial qui apparaît lorsqu'un utilisateur appuie à l'intérieur d'un champ EditText (l'IME normal ne peut plus être affiché).

Je souhaite que le clavier soit désactivé (visibilité = GONE) lorsque l'utilisateur appuie sur le bouton Retour (comme avec un service IME normal), mais que la boîte de dialogue reste visible. Cependant, il ne semble pas y avoir de moyen de faire cela autant que je puisse le voir d'après mes lectures assez approfondies sur SO et ailleurs.

Si je règle la boîte de dialogue sur non annulable, je ne reçois aucune notification de onCancel () ou onDismiss (), car cette boîte de dialogue n'est pas annulable.

Si je configure la boîte de dialogue pour pouvoir être annulée, je suis averti, mais la boîte de dialogue est fermée.

Je ne parviens pas à associer un onKeyListener à la boîte de dialogue du fragment car celui-ci est remplacé par le système afin que le fragment puisse gérer le cycle de vie de la boîte de dialogue.

Y a-t-il un moyen de faire ça? Ou bien l’accès à la détection des événements clés a-t-il été entièrement isolé pour les besoins du système Fragment?

54
user3227652

La méthode la plus propre et la plus propre consiste à remplacer onBackPressed () dans la boîte de dialogue créée dans onCreateDialog ().

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

J'ai eu le même problème que vous et je l'ai résolu en joignant le onKeyListener au dialogfragment.

Dans la méthode onResume() de la classe qui s'étend de DialogFragment, placez ce morceau 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
        }
    });

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 lorsqu'il le quitte. 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
        }
    });
}
56

En tant qu'additif à la réponse de Juan Pedro Martinez, j'ai pensé qu'il serait utile de clarifier une question spécifique (une de celles que j'avais) lorsque je regarde ce fil.

Si vous souhaitez créer un nouveau DialogFragment et le faire en sorte que l'utilisateur ne puisse l'annuler qu'en utilisant le bouton Précédent, ce qui évite que des touches d'écran aléatoires annulent le fragment prématurément, il s'agit du code que vous utiliseriez.

Quel que soit le code que vous appelez le DialogFragment, vous devez définir le paramètre annulable sur false afin que rien ne supprime le fragment, aucun contact d’écran égaré, 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 dialogue écoute le bouton Précédent. Quand il est pressé, il exécutera la méthode ignore () 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 dialogue sera appelée avec "setCancelable" sur false, ce qui signifie que rien (pas de clics extérieurs) ne peut l'annuler et la fermer, et n'autorisant (à partir de la boîte de dialogue elle-même) que le bouton Précédent pour la fermer.

Ganbatte!

17
Brandon

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;
}
6
user6367733

Utilisez la méthode de substitution Fragment onCancel. Ca s'appelle quand on appuie en arrière . En voici un exemple: 

@Override
public void onCancel(DialogInterface dialog) {
    super.onCancel(dialog);

    // Add you codition
}
2
Manimaran A

Lorsque vous créez la boîte de dialogue, remplacez 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
                    ...
            }
        };
0
android developer
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new Dialog(getActivity(), getTheme()) {
        @Override
        public void onBackPressed() {
            //your code
        }
    };

    return dialog;
}
0
Abror Esonaliyev

Utiliser le rappel onDismiss () de DialogFragment avec un indicateur closeActivity

private var closeActivity: Boolean = true    

override fun onDismiss(dialog: DialogInterface?) {
        super.onDismiss(dialog)

        if (closeActivity) {
            activity!!.finish()
        }
    }
0
Vasudev