Comment conserver le nouveau mode immersif lorsque mes activités affichent une boîte de dialogue personnalisée?
J'utilise le code ci-dessous pour maintenir le mode immersif dans les dialogues, mais avec cette solution, la NavBar apparaît pendant moins d'une seconde lorsque je démarre ma boîte de dialogue personnalisée, puis elle disparaît.
La vidéo suivante explique mieux le problème (regardez en bas de l'écran lorsque la NavBar apparaît): http://youtu.be/epnd5ghey8g
Comment éviter ce comportement?
CODE
Le père de toutes les activités de ma candidature:
public abstract class ImmersiveActivity extends Activity {
@SuppressLint("NewApi")
private void disableImmersiveMode() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
);
}
}
@SuppressLint("NewApi")
private void enableImmersiveMode() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
);
}
}
/**
* Set the Immersive mode or not according to its state in the settings:
* enabled or not.
*/
protected void updateSystemUiVisibility() {
// Retrieve if the Immersive mode is enabled or not.
boolean enabled = getSharedPreferences(Util.PREF_NAME, 0).getBoolean(
"immersive_mode_enabled", true);
if (enabled) enableImmersiveMode();
else disableImmersiveMode();
}
@Override
public void onResume() {
super.onResume();
updateSystemUiVisibility();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
updateSystemUiVisibility();
}
}
Tous mes dialogues personnalisés appellent cette méthode dans leur onCreate(. . .)
méthode:
/**
* Copy the visibility of the Activity that has started the dialog {@link mActivity}. If the
* activity is in Immersive mode the dialog will be in Immersive mode too and vice versa.
*/
@SuppressLint("NewApi")
private void copySystemUiVisibility() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(
mActivity.getWindow().getDecorView().getSystemUiVisibility()
);
}
}
EDIT - LA SOLUTION (merci à Beaver6813, regardez sa réponse pour plus de détails):
Toutes mes boîtes de dialogue personnalisées remplacent la méthode show de cette manière:
/**
* An hack used to show the dialogs in Immersive Mode (that is with the NavBar hidden). To
* obtain this, the method makes the dialog not focusable before showing it, change the UI
* visibility of the window like the owner activity of the dialog and then (after showing it)
* makes the dialog focusable again.
*/
@Override
public void show() {
// Set the dialog to not focusable.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
copySystemUiVisibility();
// Show the dialog with NavBar hidden.
super.show();
// Set the dialog to focusable again.
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}
Réponses:
Après de nombreuses recherches sur le problème, il existe une solution de piratage à ce problème, qui impliquait de déchirer la classe Dialog pour la trouver. La barre de navigation s'affiche lorsque la boîte de dialogue est ajoutée au gestionnaire de fenêtres, même si vous définissez la visibilité de l'interface utilisateur avant de l'ajouter au gestionnaire. Dans l' exemple Android Immersive, il est commenté que:
Je crois que c'est ce que nous voyons ici (qu'une interaction utilisateur est déclenchée lorsqu'une nouvelle vue de fenêtre focalisable est ajoutée au gestionnaire).
Comment pouvons-nous contourner cela? Rendre la boîte de dialogue non focalisable lorsque nous la créons (afin de ne pas déclencher d'interaction utilisateur), puis la rendre focusable après son affichage.
Ce n'est clairement pas l'idéal mais cela semble être un bogue Android, ils devraient vérifier si la fenêtre a un ensemble immersif.
J'ai mis à jour mon code de test de travail (pardonnez le désordre hacky) sur Github . J'ai testé sur l'émulateur Nexus 5, il explosera probablement avec rien de moins que KitKat, mais c'est uniquement pour une preuve de concept.
la source
Pour votre information, grâce à la réponse de @ Beaver6813, j'ai pu faire fonctionner cela en utilisant DialogFragment.
dans la méthode onCreateView de mon DialogFragment, je viens d'ajouter ce qui suit:
la source
Si vous souhaitez utiliser onCreateDialog () , essayez cette classe. Cela marche plutôt bien pour moi...
Pour afficher la boîte de dialogue, procédez comme suit dans votre activité ...
la source
En combinant les réponses ici, j'ai créé une classe abstraite qui fonctionne dans tous les cas:
la source
Cela fonctionne également sur la méthode onDismiss de votre fragment de dialogue. Et dans cette méthode, appelez la méthode de l'activité à laquelle elle est attachée pour définir à nouveau les indicateurs de plein écran.
Et dans votre activité ajoutez cette méthode:
la source
AlertDialog.Builder
et.setOnDismissListener()
Lorsque vous créez votre propre DialogFragment, il vous suffit de remplacer cette méthode.
la source
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
boîte de dialogue après affichéeJe sais que c'est un ancien message, mais ma réponse peut aider les autres.
Voici le correctif hacky pour l'effet immersif dans les dialogues:
la source