¿Cómo mantengo el nuevo modo inmersivo cuando mis actividades muestran un diálogo personalizado?
Estoy usando el código siguiente para mantener el modo inmersivo en los cuadros de diálogo, pero con esa solución, la barra de navegación aparece durante menos de un segundo cuando inicio mi cuadro de diálogo personalizado y luego desaparece.
El siguiente video explica mejor el problema (mire la parte inferior de la pantalla cuando aparezca la barra de navegación): http://youtu.be/epnd5ghey8g
¿Cómo evito este comportamiento?
CÓDIGO
El padre de todas las actividades en mi aplicación:
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();
}
}
Todos mis cuadros de diálogo personalizados llaman a este método en su onCreate(. . .)
método:
/**
* 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()
);
}
}
EDITAR - LA SOLUCIÓN (gracias a Beaver6813, busque su respuesta para obtener más detalles):
Todos mis cuadros de diálogo personalizados anulan el método show de esta manera:
/**
* 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);
}
Respuestas:
Después de mucha investigación sobre el problema, hay una solución hacky para esto, que involucró destrozar la clase Dialog para encontrar. La barra de navegación se muestra cuando la ventana de diálogo se agrega al Administrador de ventanas, incluso si configura la visibilidad de la interfaz de usuario antes de agregarla al administrador. En el ejemplo de Android Immersive se comenta que:
Creo que eso es lo que estamos viendo aquí (que se activa una interacción del usuario cuando se agrega una nueva vista de ventana enfocable al administrador).
¿Cómo podemos solucionar esto? Hacer que el diálogo no se pueda enfocar cuando lo creamos (para que no activemos una interacción del usuario) y luego hacer que se pueda enfocar después de que se muestre.
Claramente, esto no es ideal, pero parece ser un error de Android, deberían verificar si la ventana tiene un conjunto inmersivo.
Actualicé mi código de prueba de trabajo (perdona el desorden hacky) a Github . Probé en el emulador de Nexus 5, probablemente explote con algo menos que KitKat, pero es solo para prueba de concepto.
fuente
Para su información, gracias a la respuesta de @ Beaver6813, he podido hacer que esto funcione usando DialogFragment.
en el método onCreateView de mi DialogFragment, acabo de agregar lo siguiente:
fuente
Si desea utilizar onCreateDialog () , pruebe esta clase. Funciona bastante bien para mí...
Para mostrar el cuadro de diálogo, haga lo siguiente en su actividad ...
fuente
Combinando las respuestas aquí hice una clase abstracta que funciona en todos los casos:
fuente
Esto también funciona sobre el método onDismiss de su fragmento de diálogo. Y dentro de ese método, llame al método de la actividad a la que está adjunto, establezca nuevamente los indicadores de pantalla completa.
Y en tu actividad agrega este método:
fuente
AlertDialog.Builder
y.setOnDismissListener()
Cuando está creando su propio DialogFragment, solo necesita anular este método.
fuente
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
cuadro de diálogo posterior que se muestraSé que esta es una publicación antigua, pero mi respuesta puede ayudar a otros.
A continuación se muestra la solución hacky para el efecto inmersivo en los diálogos:
fuente