android user-interface android-6.0-marshmallow android-statusbar

Barra de estado de Android M Light y Dark mediante programación: ¿cómo volverlo a oscurecer?



user-interface android-6.0-marshmallow (6)

En el Android M tenemos la capacidad de hacer que los iconos de la barra de estado estén oscuros. Para ello podemos especificar el atributo en el xml del tema:

<item name="android:windowLightStatusBar">true</item>

O lo podemos configurar en tiempo de ejecución con este código:

View someView = findViewById(R.id.some_view); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { someView.setSystemUiVisibility(someView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); }

Y en realidad funciona bien. ¿Pero la pregunta es cómo configurar correctamente un modo de barra de estado como oscuro en el tiempo de ejecución?

Ya probé esas variantes:

// Makes status bar mode dark, but also hides it along with all navigation views. someView.setSystemUiVisibility(someView.getSystemUiVisibility() | ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); // Does nothing someView.setSystemUiVisibility(someView.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); // Also does nothing someView.setSystemUiVisibility(someView.getSystemUiVisibility() ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

Entonces, ¿cómo se puede hacer de una manera correcta?


Basado en la respuesta de @phan-van-linh, escribí esta clase para Android Xamarin

public static class ActivityExtensions { public static void SetLightStatusBar(this Activity activity) { int flags = (int)activity.Window.DecorView.SystemUiVisibility; // get current flag flags |= (int)SystemUiFlags.LightStatusBar; // add LIGHT_STATUS_BAR to flag activity.Window.DecorView.SystemUiVisibility = (StatusBarVisibility)flags; //activity.Window.SetStatusBarColor(Color.GRAY); // optional } public static void ClearLightStatusBar(this Activity activity) { int flags = (int)activity.Window.DecorView.SystemUiVisibility; // get current flag flags = flags ^ (int)SystemUiFlags.LightStatusBar; // use XOR here for remove LIGHT_STATUS_BAR from flags activity.Window.DecorView.SystemUiVisibility = (StatusBarVisibility)flags; //activity.Window.setStatusBarColor(Color.GREEN); // optional } }


La solución publicada por @Aracem es válida, pero no funciona si intenta cambiar también el color de fondo de la barra de estado. En mi caso lo hago de la siguiente manera.

Para habilitar windowLightStatusBar (por ejemplo, dentro de una clase de Utils):

public static void setLightStatusBar(View view,Activity activity){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int flags = view.getSystemUiVisibility(); flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; view.setSystemUiVisibility(flags); activity.getWindow().setStatusBarColor(Color.WHITE); } }

Para restaurar a StatusBar al estado anterior:

public static void clearLightStatusBar(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Window window = activity.getWindow(); window.setStatusBarColor(ContextCompat .getColor(activity,R.color.colorPrimaryDark)); } }

Restaurar el color de la barra de estado es suficiente, también restaura los colores de los iconos. MUY IMPORTANTE: la operación de restauración no se producirá hasta que la vista utilizada en setLightStatusBar (Vista vista ..) desaparezca (es decir, view.getVisibility () == GONE | INVISIBLE) de la pantalla.


Me baso en @Aracem y @Carlos Hernández Gil, pero creo que será fácil de entender si usamos XOR en modo bit (operador ^ en Java)

private void setLightStatusBar(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int flags = activity.getWindow().getDecorView().getSystemUiVisibility(); // get current flag flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // add LIGHT_STATUS_BAR to flag activity.getWindow().getDecorView().setSystemUiVisibility(flags); activity.getWindow().setStatusBarColor(Color.GRAY); // optional } } private void clearLightStatusBar(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int flags = activity.getWindow().getDecorView().getSystemUiVisibility(); // get current flag flags = flags ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // use XOR here for remove LIGHT_STATUS_BAR from flags activity.getWindow().getDecorView().setSystemUiVisibility(flags); activity.getWindow().setStatusBarColor(Color.GREEN); // optional } }

Explique

Primero, mire SYSTEM_UI_FLAG_LIGHT_STATUS_BAR y setSystemUiVisibility

/** * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that * is compatible with light status bar backgrounds. */ public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000; public void setSystemUiVisibility(int visibility) { if (visibility != mSystemUiVisibility) { mSystemUiVisibility = visibility; ... } }

Creo que el código de 2 líneas a continuación es bastante difícil de entender

flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // for set light status bar flags = flags ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // for clear light status bar

A primera vista, creo que podemos usar simples como

flags = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // for set light status bar flags = 0; // for clear light status bar (0 <=> LIGHT_STATUS_BAR <=> default systemUiVisibility)

Pero debemos usar | y ^ porque
Por ejemplo, queremos configurar tanto la barra de estado como la barra de navegación, luego usaremos

flags = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; activity.getWindow().getDecorView().setSystemUiVisibility(flags);

Cuando no queremos que la barra de estado sea más liviana, podemos usar

flags = View.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; activity.getWindow().getDecorView().setSystemUiVisibility(flags);

O

flags = activity.getWindow().getDecorView().getSystemUiVisibility(); flags = flags ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; activity.getWindow().getDecorView().setSystemUiVisibility(flags);

Para saber más por qué usamos | y ^ , creo que el siguiente tutorial puede ayudar https://medium.com/@JakobUlbrich/flag-attributes-in-android-how-to-use-them-ac4ec8aee7d1 Aquí está mi comprensión. Espero que esto ayude


Reuní este sencillo objeto de utilidad que le permite cambiar el color de la barra de estado y la barra de estado de la luz de encendido / apagado para cualquier fragmento. Sin embargo, esto se basa en el uso del componente de navegación de Android Jetpack para la navegación (Kotlin):

object StatusBarUtil { fun changeStatusBarColor(activity: Activity, @ColorInt color: Int, lightStatusBar: Boolean) { activity.window?.let { win -> val nav = Navigation.findNavController(activity, R.id.your_nav_host_fragmen /* TODO: Use the ID of your nav host fragment */) val currentDest = nav.currentDestination?.id val oldColor = win.statusBarColor val oldFlags = win.decorView.systemUiVisibility win.statusBarColor = color if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { var flags = oldFlags flags = if (lightStatusBar) { flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR } else { flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() } win.decorView.systemUiVisibility = flags } nav.addOnNavigatedListener { _, dest -> if (dest.id != currentDest) { win.statusBarColor = oldColor win.decorView.systemUiVisibility = oldFlags } } } } }

Para usar esto, llame a lo siguiente desde onViewCreated cualquier fragmento:

StatusBarUtil.changeStatusBarColor(requireActivity(), someDarkColor, false)


Según el proyecto de Nick Butcher "Plaid".

public static void clearLightStatusBar(@NonNull View view) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int flags = view.getSystemUiVisibility(); flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; view.setSystemUiVisibility(flags); } }

Puedes encontrar el proyecto Here


Voy a hacer algunos cambios en las respuestas anteriores.

hacer una clase

public class DarkStatusBar { public static void setLightStatusBar(View view, Activity activity){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int flags = view.getSystemUiVisibility(); flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; view.setSystemUiVisibility(flags); activity.getWindow().setStatusBarColor(Color.WHITE); } } }

y llámalo donde quieras así

Window window = getWindow(); View view = window.getDecorView(); DarkStatusBar.setLightStatusBar(view,this);