98 votes

Empêcher le rejet de la boîte de dialogue en cas de rotation de l'écran dans Android

J'essaie d'empêcher les boîtes de dialogue construites avec Alert builder d'être rejetées lorsque l'activité est redémarrée.

Si je surcharge la méthode onConfigurationChanged, je peux le faire avec succès et réinitialiser la mise en page à l'orientation correcte, mais je perds la fonction de texte collant de l'edittext. Ainsi, en résolvant le problème du dialogue, j'ai créé ce problème d'edittext.

Si je sauvegarde les chaînes de caractères du texte d'édition et que je les réaffecte dans le changement d'onCofiguration, elles semblent toujours avoir la valeur initiale par défaut et non celle qui a été saisie avant la rotation. Même si je force une invalidation, cela semble les mettre à jour.

J'ai vraiment besoin de résoudre soit le problème du dialogue, soit celui de l'édition du texte.

Merci pour votre aide.

1 votes

Comment enregistrer/restaurer le contenu de l'EditText modifié ? Pouvez-vous montrer un peu de code ?

0 votes

J'ai compris le problème, j'avais oublié de récupérer la vue par Id après avoir réinitialisé la mise en page.

0voto

Amir Golan Points 51

Si rien ne vous aide et que vous avez besoin d'une solution qui fonctionne, vous pouvez opter pour la sécurité et, à chaque fois que vous ouvrez un dialogue, sauvegarder ses informations de base dans le ViewModel de l'activité (et les supprimer de cette liste lorsque vous fermez le dialogue). Ces informations de base peuvent être le type de dialogue et un identifiant (les informations dont vous avez besoin pour ouvrir ce dialogue). Ce ViewModel n'est pas détruit pendant les changements du cycle de vie de l'activité. Disons que l'utilisateur ouvre une boîte de dialogue pour laisser une référence à un restaurant. Le type de dialogue serait donc LeaveReferenceDialog et l'id serait l'id du restaurant. Lorsque vous ouvrez cette boîte de dialogue, vous enregistrez ces informations dans un objet que vous pouvez appeler DialogInfo, et vous ajoutez cet objet au ViewModel de l'activité. Ces informations vous permettront de rouvrir la boîte de dialogue lorsque l'activité onResume() sera appelée :

// On resume in Activity
    override fun onResume() {
            super.onResume()

            // Restore dialogs that were open before activity went to background
            restoreDialogs()
        }

Qui appelle :

    fun restoreDialogs() {
    mainActivityViewModel.setIsRestoringDialogs(true) // lock list in view model

    for (dialogInfo in mainActivityViewModel.openDialogs)
        openDialog(dialogInfo)

    mainActivityViewModel.setIsRestoringDialogs(false) // open lock
}

Lorsque IsRestoringDialogs dans ViewModel est défini à true, les informations sur les dialogues ne seront pas ajoutées à la liste dans le modèle de vue, et c'est important parce que nous restaurons maintenant les dialogues qui sont déjà dans cette liste. Sinon, modifier la liste pendant son utilisation provoquerait une exception. Donc :

// Create new dialog
        override fun openLeaveReferenceDialog(restaurantId: String) {
            var dialog = LeaveReferenceDialog()
            // Add id to dialog in bundle
            val bundle = Bundle()
            bundle.putString(Constants.RESTAURANT_ID, restaurantId)
            dialog.arguments = bundle
            dialog.show(supportFragmentManager, "")

            // Add dialog info to list of open dialogs
            addOpenDialogInfo(DialogInfo(LEAVE_REFERENCE_DIALOG, restaurantId))
    }

Ensuite, supprimez les informations de la boîte de dialogue lorsque vous la fermez :

// Dismiss dialog
override fun dismissLeaveReferenceDialog(Dialog dialog, id: String) {
   if (dialog?.isAdded()){
      dialog.dismiss()
      mainActivityViewModel.removeOpenDialog(LEAVE_REFERENCE_DIALOG, id)
   }
}

Et dans le ViewModel de l'activité :

fun addOpenDialogInfo(dialogInfo: DialogInfo){
    if (!isRestoringDialogs){
       val dialogWasInList = removeOpenDialog(dialogInfo.type, dialogInfo.id)
       openDialogs.add(dialogInfo)
     }
}

fun removeOpenDialog(type: Int, id: String) {
    if (!isRestoringDialogs)
       for (dialogInfo in openDialogs) 
         if (dialogInfo.type == type && dialogInfo.id == id) 
            openDialogs.remove(dialogInfo)
}

En fait, vous rouvrez toutes les boîtes de dialogue qui étaient ouvertes auparavant, dans le même ordre. Mais comment font-elles pour conserver leurs informations ? Chaque boîte de dialogue possède son propre ViewModel, qui n'est pas non plus détruit pendant le cycle de vie de l'activité. Ainsi, lorsque vous ouvrez la boîte de dialogue, vous obtenez le ViewModel et vous créez l'interface utilisateur en utilisant ce ViewModel de la boîte de dialogue comme toujours.

-1voto

Preetam Pal Points 1

Oui, je suis d'accord avec la solution d'utiliser DialogFragment donnée par @Brais Gabin, je veux juste suggérer quelques changements à la solution donnée par lui.

En définissant notre classe personnalisée qui étend DialogFragment, nous avons besoin de certaines interfaces pour gérer les actions finales par l'activité ou le fragment qui a invoqué le dialogue. Mais la définition de ces interfaces d'écoute dans la méthode onAttach(Context context) peut parfois provoquer une ClassCastException qui peut faire planter l'application.

Donc, pour éviter cette exception, nous pouvons créer une méthode pour définir les interfaces de l'écouteur et l'appeler juste après avoir créé l'objet du fragment de dialogue. Voici un exemple de code qui pourrait vous aider à mieux comprendre

AlertRetryDialog.class

    public class AlertRetryDialog extends DialogFragment {

       public interface Listener{
         void onRetry();
         }

    Listener listener;

     public void setListener(Listener listener)
       {
       this.listener=listener;
       }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
    AlertDialog.Builder builder=new AlertDialog.Builder(getActivity());
    builder.setMessage("Please Check Your Network Connection").setPositiveButton("Retry", new 
    DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
             //Screen rotation will cause the listener to be null
            //Always do a null check of your interface listener before calling its method
            if(listener!=null&&listener instanceof HomeFragment)
            listener.onRetry();
        }
       }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
         }
     });
     return builder.create();
    }

   }

Et dans l'activité ou dans le fragment que vous appelez

                   AlertRetryDialog alertRetryDialog = new AlertRetryDialog();
                    alertRetryDialog.setListener(HomeFragment.this);
                    alertRetryDialog.show(getFragmentManager(), "tag");

Et implémentez les méthodes de votre interface d'écoute dans votre activité ou votre fragment.

              public class YourActivity or YourFragment implements AlertRetryDialog.Listener{ 

                  //here's my listener interface's method
                    @Override
                    public void onRetry()
                    {
                     //your code for action
                      }

                 }

Veillez toujours à effectuer un contrôle de nullité des interfaces de l'écouteur avant d'appeler l'une de ses méthodes afin d'éviter une NullPointerException (la rotation de l'écran entraînera la nullité des interfaces de l'écouteur).

Veuillez me faire savoir si cette réponse vous a été utile. Merci.

-3voto

user3384694 Points 1

Il suffit d'utiliser

ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize

et l'application saura comment gérer la rotation et la taille de l'écran.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X