Lollipop: dibuja detrás de la barra de estado con su color establecido en transparente

Resuelto alxscms asked hace 54 años • 16 respuestas

He configurado el color de mi barra de estado en transparente para Lollipop solo con la siguiente línea en mi tema:

<item name="android:statusBarColor">@android:color/transparent</item>

Ahora necesito dibujar detrás de él, pero no puedo dibujar ninguna vista detrás de él. Sé cómo hacerlo con la windowTranslucentStatuspropiedad, pero no quiero usar esta propiedad ya que ignorará el color de la barra de estado establecida en transparente.

alxscms avatar Jan 01 '70 08:01 alxscms
Aceptado

Método 1:

Para lograr una barra de estado completamente transparente, debe usar statusBarColor, que solo está disponible en API 21 y superior. windowTranslucentStatusestá disponible en API 19 y superior, pero agrega un fondo teñido para la barra de estado. Sin embargo, la configuración windowTranslucentStatuslogra una cosa que cambiar statusBarColora transparente no logra: establece las banderas SYSTEM_UI_FLAG_LAYOUT_STABLE y . SYSTEM_UI_FLAG_LAYOUT_FULLSCREENLa forma más sencilla de obtener el mismo efecto es configurar manualmente estas banderas, lo que efectivamente desactiva las inserciones impuestas por el sistema de diseño de Android y te deja a tu suerte.

Llamas a esta línea en tu onCreatemétodo:

getWindow().getDecorView().setSystemUiVisibility(
    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

Asegúrese de configurar también la transparencia en /res/values-v21/styles.xml:

<item name="android:statusBarColor">@android:color/transparent</item>

O establezca la transparencia mediante programación:

getWindow().setStatusBarColor(Color.TRANSPARENT);

El lado bueno de este enfoque es que los mismos diseños también se pueden usar en API 19 cambiando la barra de estado transparente por la barra de estado translúcida teñida.

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

Método #2:

Si solo necesita pintar una imagen de fondo debajo de su barra de estado, en lugar de colocar una vista detrás de ella, esto se puede hacer simplemente configurando el fondo del tema de su actividad en la imagen deseada y configurando la transparencia de la barra de estado como se muestra en el método # 1. Este fue el método que utilicé para crear las capturas de pantalla para el artículo de Android Police de hace unos meses.

Método #3:

Si tiene que ignorar las inserciones estándar del sistema para algunos diseños y mantenerlas funcionando en otros, la única forma viable de hacerlo es trabajar con la ScrimInsetsFrameLayoutclase frecuentemente vinculada. Por supuesto, algunas de las cosas que se hacen en esa clase no son necesarias para todos los escenarios. Por ejemplo, si no planea utilizar la superposición de la barra de estado sintética, simplemente comente todo el contenido del init()método y no se moleste en agregar nada al archivo attrs.xml. He visto que este enfoque funciona, pero creo que encontrará otras implicaciones que pueden requerir mucho trabajo.

También vi que te opones a incluir múltiples diseños. En el caso de envolver un diseño dentro de otro, donde ambos tienen match_parentaltura y ancho, las implicaciones en el rendimiento son demasiado triviales como para preocuparse. De todos modos, puedes evitar esa situación por completo cambiando la clase desde la que se extiende FrameLayouta cualquier otro tipo de clase de Diseño que desees. Funcionará bien.

Cody Toombs avatar Jan 20 '2015 09:01 Cody Toombs

Esto funcionó para mi caso.


// Create/Set toolbar as actionbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

// Check if the version of Android is Lollipop or higher
if (Build.VERSION.SDK_INT >= 21) {

    // Set the status bar to dark-semi-transparentish
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
            WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    // Set paddingTop of toolbar to height of status bar.
    // Fixes statusbar covers toolbar issue
    toolbar.setPadding(0, getStatusBarHeight(), 0, 0);
}

// A method to find height of the status bar
public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

Para obtener más información sobre cómo trabajar con barras de estado: youtube.com/watch?v=_mGDMVRO3iE


Michael avatar Mar 26 '2015 14:03 Michael

Prueba este tema

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="colorPrimaryDark">@android:color/transparent</item>
    <item name="colorPrimary">@color/md_blue_200</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>

Asegúrese de que su conjunto de diseño

android:fitsSystemWindows="false"
Son Nguyen Thanh avatar Oct 13 '2015 05:10 Son Nguyen Thanh

La solución de Cody Toombs casi me funcionó. No estoy seguro de si esto está relacionado con Xamarin o no, pero ahora tengo una solución aceptable:

Ejemplo

Esta es mi configuración:

Tengo un proyecto de Android en el que hice referencia a los paquetes Android.Support v4 y v7. Tengo dos estilos definidos:

valores/estilos.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <style name="MyStyle" parent="@style/Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
    </style>
</resources>

valores-v21/styles.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <style name="MyStyle" parent="@style/Theme.AppCompat.Light.NoActionBar">
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

AndroidManifest apunta a "MyStyle":

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.agn.test.test">
    <uses-sdk android:minSdkVersion="10" />
    <application android:allowBackup="true" android:icon="@mipmap/icon" android:label="@string/app_name" android:theme="@style/MyStyle">
    </application>
</manifest>

Y finalmente el código en la Actividad Principal:

[Activity (Label = "Test", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity : Activity
{
    protected override void OnCreate (Bundle savedInstanceState)
    {
        base.OnCreate (savedInstanceState);

        SetContentView (Resource.Layout.Main);
        //Resource.Layout.Main is just a regular layout, no additional flags. Make sure there is something in there like an imageView, so that you can see the overlay.

        var uiOptions = (int)Window.DecorView.SystemUiVisibility;
        uiOptions ^= (int)SystemUiFlags.LayoutStable;
        uiOptions ^= (int)SystemUiFlags.LayoutFullscreen;
        Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;

        Window.AddFlags (WindowManagerFlags.DrawsSystemBarBackgrounds);
    }
}

Observe que configuré el indicador DrawsSystemBarBackgrounds, esto marca la diferencia

Window.AddFlags (WindowManagerFlags.DrawsSystemBarBackgrounds); 

Pasé mucho tiempo haciéndolo bien; de hecho, demasiado tiempo. Esperemos que esta respuesta ayude a cualquiera que intente lograr lo mismo.

Gerhard Schreurs avatar Jun 28 '2016 14:06 Gerhard Schreurs