El cajón de navegación semi-transparente sobre la barra de estado no funciona

Estoy trabajando en el proyecto de Android y estoy implementando el cajón de navegación. Estoy leyendo la nueva especificación de diseño de material y la lista de materiales de diseño .
La especificación dice que el panel deslizante debe flotar por encima de todo lo demás, incluyendo la barra de estado y ser semi-transparente sobre la barra de estado.

Mi panel de navegación está sobre la barra de estado pero no tiene ninguna transparencia. He seguido el código de esta publicación SO como se sugiere en el blog de desarrolladores de Google lugar, enlace anterior ¿Cómo puedo utilizar DrawerLayout para mostrar en la Barra de Acción / Barra de herramientas y en la barra de estado? .

A continuación se muestra mi diseño XML

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/my_drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.Toolbar android:id="@+id/my_awesome_toolbar" android:layout_height="wrap_content" android:layout_width="match_parent" android:minHeight="?attr/actionBarSize" android:background="@color/appPrimaryColour" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout" android:layout_width="304dp" android:layout_height="match_parent" android:layout_gravity="left|start" android:fitsSystemWindows="true" android:background="#ffffff"> <ListView android:id="@+id/left_drawer" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="singleChoice"></ListView> </LinearLayout> </android.support.v4.widget.DrawerLayout> 

A continuación se muestra el tema de mis aplicaciones

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/appPrimaryColour</item> <item name="colorPrimaryDark">@color/appPrimaryColourDark</item> <item name="colorAccent">@color/appPrimaryColour</item> <item name="windowActionBar">false</item> <item name="windowActionModeOverlay">true</item> </style> 

A continuación se muestra el tema de mis aplicaciones v21

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/appPrimaryColour</item> <item name="colorPrimaryDark">@color/appPrimaryColourDark</item> <item name="colorAccent">@color/appPrimaryColour</item> <item name="windowActionBar">false</item> <item name="windowActionModeOverlay">true</item> <item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@android:color/transparent</item> </style> 

A continuación se muestra mi método onCreate

 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar); setSupportActionBar(toolbar); mDrawerLayout = (DrawerLayout)findViewById(R.id.my_drawer_layout); mDrawerList = (ListView)findViewById(R.id.left_drawer); mDrawerLayout.setStatusBarBackgroundColor( getResources().getColor(R.color.appPrimaryColourDark)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { LinearLayout linearLayout = (LinearLayout)findViewById(R.id.linearLayout); linearLayout.setElevation(30); } 

A continuación se muestra una captura de pantalla de mi cajón de navegación mostrando que la parte superior no es semi transparente

Captura de pantalla que no es transparente en la barra de estado

Su fondo de la barra de estado es blanco, el fondo de su gaveta LinearLayout . ¿Por qué? Usted es ajustes fitsSystemWindows="true" para su DrawerLayout y el LinearLayout dentro de él. Esto hace que LinearLayout expanda detrás de la barra de estado (que es transparente). Por lo tanto, hacer que el fondo de la parte del cajón de la barra de estado sea blanco.

Introduzca aquí la descripción de la imagen
Si no desea que su cajón se extienda detrás de la barra de estado (quiere tener un fondo semitransparente para toda la barra de estado), puede hacer dos cosas:

1) Usted puede simplemente quitar cualquier valor de fondo de su LinearLayout y colorear el fondo de su contenido dentro de él. O

2) Puede quitar fitsSystemWindows="true" de su LinearLayout . Creo que este es un enfoque más lógico y más limpio. También evitará que se proyecte una sombra debajo de la barra de estado, donde no se extiende el cajón de navegación.

Introduzca aquí la descripción de la imagen
Si desea que su cajón se extienda detrás de la barra de estado y tenga una superposición semitransparente de tamaño de barra de estado, puede utilizar ScrimInsetFrameLayout como contenedor para el contenido del cajón ( ListView ) y establecer el fondo de la barra de estado utilizando app:insetForeground="#4000" . Por supuesto, puede cambiar #4000 a cualquier cosa que desee. No te olvides de mantener fitsSystemWindows="true" aquí!

O si no desea superponer su contenido y sólo mostrar un color sólido, sólo puede configurar el fondo de su LinearLayout a cualquier cosa que desee. No te olvides de establecer el fondo de tu contenido por separado sin embargo!

EDIT: Ya no es necesario tratar con nada de esto. Consulte la Biblioteca de soporte de diseño para ver una implementación de Gavetas / vistas más sencilla.

Todo lo que necesitas hacer es usar un poco de color semi-transparente para la barra de estado. Añada estas líneas a su tema v21:

 <item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@color/desired_color</item> 

No olvide que el color (recurso) debe estar siempre en el formato de #AARRGGBB . Esto significa que el color también incluirá el valor alfa.

¿Por qué no usar algo similar a esto?

 <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent"/> <ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" android:background="#80111111"/> </android.support.v4.widget.DrawerLayout> 

El código anterior usa el recurso alfa en el android:background para poder mostrar transparencia dentro de la barra de acción.

Hay otras maneras de hacerlo a través del código, como muestran otras respuestas. Mi respuesta anterior, hace lo necesario en el archivo de diseño xml, que en mi opinión es fácil de editar.

Usted necesita para envolver su diseño de cajón de navegación dentro de un ScrimLayout .

Un ScrimLayout dibuja básicamente un rectángulo semitransparente sobre su disposición del cajón de la navegación. Para recuperar el tamaño de la inserción simplemente anule fitSystemWindows en su ScrimLayout .

 @Override protected boolean fitSystemWindows(Rect insets) { mInsets = new Rect(insets); return true; } 

Posteriormente anulará onDraw para dibujar un rectángulo semitransparente.

Un ejemplo de implementación se puede encontrar en la fuente de Google IO App. Aquí puedes ver cómo se usa en el layout xml.

Si desea que el panel de navegación esté sobre la barra de estado y sea semitransparente sobre la barra de estado. Google I / O Android App Source proporciona una buena solución ( APK en Play Store no se actualiza a la última versión)

Primero necesitas un ScrimInsetFrameLayout

 /* * Copyright 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * A layout that draws something in the insets passed to {@link #fitSystemWindows(Rect)}, ie the area above UI chrome * (status and navigation bars, overlay action bars). */ public class ScrimInsetsFrameLayout extends FrameLayout { private Drawable mInsetForeground; private Rect mInsets; private Rect mTempRect = new Rect(); private OnInsetsCallback mOnInsetsCallback; public ScrimInsetsFrameLayout(Context context) { super(context); init(context, null, 0); } public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public ScrimInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AttributeSet attrs, int defStyle) { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ScrimInsetsView, defStyle, 0); if (a == null) { return; } mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsView_insetForeground); a.recycle(); setWillNotDraw(true); } @Override protected boolean fitSystemWindows(Rect insets) { mInsets = new Rect(insets); setWillNotDraw(mInsetForeground == null); ViewCompat.postInvalidateOnAnimation(this); if (mOnInsetsCallback != null) { mOnInsetsCallback.onInsetsChanged(insets); } return true; // consume insets } @Override public void draw(Canvas canvas) { super.draw(canvas); int width = getWidth(); int height = getHeight(); if (mInsets != null && mInsetForeground != null) { int sc = canvas.save(); canvas.translate(getScrollX(), getScrollY()); // Top mTempRect.set(0, 0, width, mInsets.top); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); // Bottom mTempRect.set(0, height - mInsets.bottom, width, height); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); // Left mTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); // Right mTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); canvas.restoreToCount(sc); } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (mInsetForeground != null) { mInsetForeground.setCallback(this); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mInsetForeground != null) { mInsetForeground.setCallback(null); } } /** * Allows the calling container to specify a callback for custom processing when insets change (ie when * {@link #fitSystemWindows(Rect)} is called. This is useful for setting padding on UI elements based on * UI chrome insets (eg a Google Map or a ListView). When using with ListView or GridView, remember to set * clipToPadding to false. */ public void setOnInsetsCallback(OnInsetsCallback onInsetsCallback) { mOnInsetsCallback = onInsetsCallback; } public static interface OnInsetsCallback { public void onInsetsChanged(Rect insets); } } 

Entonces, en tu diseño XML cambia esta parte

 <LinearLayout android:id="@+id/linearLayout" android:layout_width="304dp" android:layout_height="match_parent" android:layout_gravity="left|start" android:fitsSystemWindows="true" android:background="#ffffff"> <ListView android:id="@+id/left_drawer" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="singleChoice"></ListView> </LinearLayout> 

Cambiar LinearLayout a su ScrimInsetFrameLayout como este

 <com.boardy.util.ScrimInsetFrameLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/linearLayout" android:layout_width="304dp" android:layout_height="match_parent" android:layout_gravity="left|start" android:fitsSystemWindows="true" app:insetForeground="#4000"> <ListView android:id="@+id/left_drawer" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="singleChoice"></ListView> </com.boardy.util.ScrimInsetFrameLayout> 

Tenía una característica similar a poner en práctica en mi proyecto. Y para hacer mi cajón transparente sólo uso la transparencia para los colores hexadecimales . Usando 6 dígitos hexadecimales, tiene 2 dígitos hexadecimales para cada valor de rojo, verde y azul respectivamente. Pero si usted pone dos dígitos adicionales (8 dígitos hexadecimales), por lo que tiene ARGB (dos dígitos para el valor alfa) ( Mira aquí ).

Aquí están los Valores de Opacidad Hex: para los 2 dígitos adicionales

 100% — FF 95% — F2 90% — E6 85% — D9 80% — CC 75% — BF 70% — B3 65% — A6 60% — 99 55% — 8C 50% — 80 45% — 73 40% — 66 35% — 59 30% — 4D 25% — 40 20% — 33 15% — 26 10% — 1A 5% — 0D 0% — 00 

Por ejemplo: si tiene el color hex (# 111111) sólo tiene que poner uno de los valores de opacidad para obtener transparencia. Como esto: (# 11111100)

Mi cajón no cubre la barra de acción (como la tuya), pero la transparencia también se puede aplicar en estos casos. Aquí está mi código:

  <ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:background="#11111100" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" /> </android.support.v4.widget.DrawerLayout> 

Y aquí hay otro artículo que puede ayudarle a entender los códigos alfa en colores hexadecimales.

Todas las respuestas mencionadas aquí son demasiado viejas y largas. La solución mejor y corta que funciona con la última vista de navegación es

 @Override public void onDrawerSlide(View drawerView, float slideOffset) { super.onDrawerSlide(drawerView, slideOffset); try { //int currentapiVersion = android.os.Build.VERSION.SDK_INT; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){ // Do something for lollipop and above versions Window window = getWindow(); // clear FLAG_TRANSLUCENT_STATUS flag: window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); // finally change the color to any color with transparency window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDarktrans));} } catch (Exception e) { Crashlytics.logException(e); } } 

Esto va a cambiar su color de barra de estado a transparente cuando abra el cajón

Ahora, cuando cierres el cajón, debes volver a cambiar el color de la barra de estado a la oscuridad. Así puedes hacerlo de esta manera.

 @Override public void onDrawerClosed(View drawerView) { super.onDrawerClosed(drawerView); try { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { // Do something for lollipop and above versions Window window = getWindow(); // clear FLAG_TRANSLUCENT_STATUS flag: window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); // finally change the color again to dark window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark)); } } catch (Exception e) { Crashlytics.logException(e); } } 

Y luego en el diseño principal, añada una sola línea, es decir

  android:fitsSystemWindows="true" 

Y su diseño de cajón se verá como

  <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:fitsSystemWindows="true" android:layout_width="match_parent" android:layout_height="match_parent"> 

Y su vista de navegación se verá como

  <android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_height="match_parent" android:layout_width="wrap_content" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/navigation_header" app:menu="@menu/drawer" /> 

Lo he probado y su totalmente working.Hope ayuda a someone.This no puede ser el mejor enfoque, pero funciona sin problemas y es fácil de implementar. Marcarlo para arriba si ayuda. Codificación feliz 🙂

  • Barra de herramientas de AppCompat: establece el tema de la barra de herramientas desde el tema superior
  • Los botones de la barra de herramientas no responden al tacto cuando está abierto un cajón de navegación
  • ¿Cómo hacer que el menú emergente de desbordamiento evite obstruir la barra de acción?
  • Cambiar la visibilidad Las vistas de AppBarLayout causan problemas de espaciado para Fragments cargados
  • Reemplazar el diseño de la barra de herramientas de acuerdo con el fragmento visualizado
  • Fuente personalizada para el mensaje de error de TextInputLayout en android
  • Extender clases de preferencia en Android Lollipop = perder animación
  • FloatingActionButton expandir en una nueva actividad
  • Barra de estado y barra de estado translúcida
  • ¿Cómo implementar costuras en el diseño de materiales en android?
  • Android - Color del botón material
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.