Cajón de navegación semitransparente sobre la barra de estado no funciona

Estoy trabajando en un proyecto de Android y estoy implementando el Cajón de navegación. Estoy leyendo las nuevas Especificaciones de diseño de materiales y la Lista de verificación de diseño de materiales .
La especificación dice que el panel deslizable debe flotar sobre todo lo demás, incluida la barra de estado, y ser semitransparente 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 de SO tal como se sugiere en el blog de desarrolladores de Google, enlace anterior. ¿Cómo uso DrawerLayout para mostrar en la Barra de herramientas / Barra de herramientas y debajo de la barra de estado? .

A continuación está mi diseño XML

        

A continuación está mi tema de aplicaciones

  @color/appPrimaryColour @color/appPrimaryColourDark @color/appPrimaryColour false true  

A continuación está mi tema de aplicaciones v21

  @color/appPrimaryColour @color/appPrimaryColourDark @color/appPrimaryColour false true true @android:color/transparent  

A continuación está 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 que muestra que la parte superior no es semi transparente

Captura de pantalla que muestra no transparente sobre la barra de estado

El fondo de la barra de estado es blanco, el fondo de su cajón LinearLayout . ¿Por qué? Usted es ajustes fitsSystemWindows="true" para su DrawerLayout y 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 para la parte del cajón de la barra de estado sea blanco.

enter image description here
Si no desea que su cajón se extienda detrás de la barra de estado (desea tener un fondo semitransparente para toda la barra de estado), puede hacer dos cosas:

1) Simplemente puede eliminar cualquier valor de fondo de su LinearLayout y colorear el fondo de su contenido dentro de él. O

2) Puede eliminar 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 su panel de navegación no se extiende.

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

O si no desea superponer su contenido y solo muestra un color sólido, puede establecer el fondo de su LinearLayout en todo lo que desee. Sin embargo, ¡no olvide configurar el fondo de su contenido por separado!

EDITAR: Ya no es necesario tratar con nada de esto. Consulte Design Support Library para una implementación de Cajón de navegación / Vista mucho más fácil.

Todo lo que necesita hacer es usar un poco de color semitransparente para la barra de estado. Agregue estas líneas a su tema v21:

 true @color/desired_color 

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

¿Por qué no usar algo similar a esto?

     

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

Hay otras formas 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.

ScrimLayout ajustar el diseño de su cajón de navegación dentro de ScrimLayout .

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

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

Más tarde anule el onDraw para dibujar un rectángulo semitransparente.

Se puede encontrar una implementación de ejemplo en la fuente de la aplicación Google IO. Aquí puede ver cómo se usa en el diseño 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 versión perdida)

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.restreToCount(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); } } 

Luego, en su diseño XML, cambie esta parte

    

Cambie LinearLayout a su ScrimInsetFrameLayout como este

    

Tenía una característica similar para implementar en mi proyecto. Y para hacer que mi cajón sea transparente, simplemente uso la transparencia para los colores hexadecimales . Utilizando 6 dígitos hexadecimales, tiene 2 dígitos hexadecimales para cada valor de rojo, verde y azul, respectivamente. pero si pones dos dígitos adicionales (8 dígitos hexadecimales), entonces tienes 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 color hexagonal (n. ° 111111), simplemente coloque uno de los valores de opacidad para obtener transparencia. como este: (# 11111100)

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

    

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

Todas las respuestas mencionadas aquí son demasiado antiguas y largas. La mejor y más corta solución que funciona con la última Navigationview 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 el color de la barra de estado a transparente cuando abra el cajón

Ahora cuando cierra el cajón necesita cambiar el color de la barra de estado nuevamente a oscuro. Así puede 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 agregar una sola línea, es decir,

  android:fitsSystemWindows="true" 

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

   

y su vista de navegación se verá como

   

Lo he probado y funciona completamente. Espero que ayude a alguien. Puede que este no sea el mejor enfoque, pero funciona sin problemas y es fácil de implementar. Marcado si ayuda. Codificación feliz 🙂