Wie pflege ich den neuen Immersive-Modus, wenn meine Aktivitäten einen benutzerdefinierten Dialog anzeigen?
Ich verwende den folgenden Code, um den Immersive-Modus in Dialogen beizubehalten. Bei dieser Lösung wird die Navigationsleiste jedoch weniger als eine Sekunde lang angezeigt, wenn ich meinen benutzerdefinierten Dialog starte. Dann verschwindet sie.
Das folgende Video erklärt das Problem besser (sehen Sie am unteren Bildschirmrand nach, wenn die NavBar angezeigt wird): http://youtu.be/epnd5ghey8g
Wie vermeide ich dieses Verhalten?
CODE
Der Vater aller Aktivitäten in meiner Bewerbung:
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();
}
}
Alle meine benutzerdefinierten Dialoge rufen diese Methode in ihrer onCreate(. . .)
Methode auf:
/**
* 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 - THE SOLUTION (dank Beaver6813 finden Sie in seiner Antwort weitere Details):
Alle meine benutzerdefinierten Dialoge überschreiben die show-Methode folgendermaßen:
/**
* 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);
}
Antworten:
Nach viel Forschung in der Frage gibt es eine hacky Lösung für dieses, die neben den beteiligten Zerreißen Dialog Klasse zu finden. Die Navigationsleiste wird angezeigt, wenn das Dialogfenster zum Fenstermanager hinzugefügt wird, auch wenn Sie die Sichtbarkeit der Benutzeroberfläche festlegen, bevor Sie sie dem Manager hinzufügen. Im Android Immersive-Beispiel heißt es:
Ich glaube, das ist es, was wir hier sehen (dass eine Benutzerinteraktion ausgelöst wird, wenn dem Manager eine neue, fokussierbare Fensteransicht hinzugefügt wird).
Wie können wir das umgehen? Machen Sie den Dialog beim Erstellen nicht fokussierbar (damit wir keine Benutzerinteraktion auslösen) und machen Sie ihn nach der Anzeige fokussierbar.
Natürlich ist dies nicht ideal, aber es scheint ein Android-Fehler zu sein. Sie sollten prüfen, ob das Fenster ein immersives Set hat.
Ich habe meinen Arbeitstestcode (verzeihen Sie die hackige Unordnung) auf Github aktualisiert . Ich habe auf dem Nexus 5-Emulator getestet, er wird wahrscheinlich mit weniger als KitKat in die Luft jagen, aber nur als Proof-of-Concept.
quelle
Zu Ihrer Information, dank der Antwort von @ Beaver6813 konnte ich dies mit DialogFragment zum Laufen bringen.
In der onCreateView-Methode meines DialogFragments habe ich gerade Folgendes hinzugefügt:
quelle
Wenn Sie onCreateDialog () verwenden möchten , versuchen Sie diese Klasse. Es funktioniert ziemlich gut für mich ...
Gehen Sie in Ihrer Aktivität wie folgt vor, um den Dialog anzuzeigen ...
quelle
Ich habe die Antworten hier kombiniert und eine abstrakte Klasse erstellt, die in allen Fällen funktioniert:
quelle
Dies funktioniert auch über die onDismiss-Methode Ihres Dialogfragments hinaus. Rufen Sie innerhalb dieser Methode die Methode der Aktivität auf, an die sie angehängt ist, um die Vollbild-Flags erneut zu setzen.
Und fügen Sie in Ihrer Aktivität diese Methode hinzu:
quelle
AlertDialog.Builder
and.setOnDismissListener()
Wenn Sie Ihr eigenes DialogFragment erstellen, müssen Sie diese Methode nur überschreiben.
quelle
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
angezeigten Nach-DialogIch weiß, dass dies ein alter Beitrag ist, aber meine Antwort kann anderen helfen.
Unten finden Sie die Hacky-Korrektur für den Immersive-Effekt in Dialogen:
quelle