Estoy trabajando en un proyecto de Android y estoy implementando Navigation Drawer. 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 transparencia. He seguido el código de esta publicación de SO como se sugiere en el sitio del blog de desarrolladores de Google, enlace arriba ¿Cómo uso DrawerLayout para mostrar sobre ActionBar / Toolbar y debajo de 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 mi aplicación
<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 mi aplicación 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 que muestra que la parte superior no es semitransparente
Respuestas:
El fondo de la barra de estado es blanco, el fondo de su cajón
LinearLayout
. ¿Por qué? Son ajustesfitsSystemWindows="true"
para ustedDrawerLayout
y suLinearLayout
interior. Esto haceLinearLayout
que se 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.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. O2) Puede eliminar
fitsSystemWindows="true"
de suLinearLayout
. 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 cajón de navegación no se extiende.Si desea que su 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 a
ScrimInsetFrameLayout
como contenedor para el contenido del cajón (ListView
) y establecer el fondo de la barra de estado usandoapp:insetForeground="#4000"
. Por supuesto, puede cambiar#4000
a lo que desee. ¡No olvides quedartefitsSystemWindows="true"
aquí!O si no desea superponer su contenido y solo mostrar un color sólido, puede configurar el fondo de su imagen
LinearLayout
como desee. Sin embargo, ¡no olvide configurar el fondo de su contenido por separado!EDITAR: Ya no necesitas lidiar con nada de esto. Consulte la Biblioteca de soporte de diseño para una implementación de vista / panel de navegación más fácil.
fuente
Todo lo que necesita hacer es usar un color semitransparente para la barra de estado. Agregue 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) siempre debe tener el formato#AARRGGBB
. Esto significa que el color también incluirá el valor alfa.fuente
¿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 acciones.Hay otras formas de hacer esto 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 se edita fácilmente.
fuente
Todas las respuestas mencionadas aquí son demasiado antiguas y extensas. 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 abras el cajón
Ahora, cuando cierre el cajón, deberá cambiar el color de la barra de estado nuevamente a oscuro, para que pueda 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 agregue una sola línea, es decir
android:fitsSystemWindows="true"
y el diseño de su 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 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. Márquelo si ayuda. Feliz codificación :)
fuente
Debe envolver el diseño del cajón de navegación dentro de un archivo
ScrimLayout
.ScrimLayout
Básicamente, A dibuja un rectángulo semitransparente sobre el diseño del cajón de navegación. Para recuperar el tamaño del recuadro, simplemente anulefitSystemWindows
suScrimLayout
.@Override protected boolean fitSystemWindows(Rect insets) { mInsets = new Rect(insets); return true; }
Posteriormente anule
onDraw
para dibujar un rectángulo semitransparente.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.
fuente
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 (los APK en Play Store no se actualizan 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)}, i.e. 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 (i.e. when * {@link #fitSystemWindows(Rect)} is called. This is useful for setting padding on UI elements based on * UI chrome insets (e.g. 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
<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>
Cambie LinearLayout a su ScrimInsetFrameLayout así
<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>
fuente
ScrimInsetsView_insetForeground
atributo.android.support.design.internal.ScrimInsetsFrameLayout
de la biblioteca de apoyoTenía una característica similar para implementar en mi proyecto. Y para que mi cajón sea transparente, solo uso la transparencia para colores hexadecimales . Con 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í ).
Estos son los valores de opacidad hexadecimal: 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 un color hexadecimal (# 111111) simplemente coloque uno de los valores de opacidad para obtener transparencia. así: (# 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 ayudarlo a comprender los códigos alfa en colores hexadecimales.
fuente
Las soluciones existentes están bastante desactualizadas. Aquí está la última solución que debería funcionar perfectamente en AndroidX o bibliotecas de materiales.
Agregue
android:fitsSystemWindows="true"
a la vista raíz de su diseño, que resulta ser DrawerLayout para su caso.Esto le dice a la Vista que use toda la pantalla para medir y diseñar, superponiéndose con la barra de estado.
Agregue lo siguiente a su estilo XML
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowTranslucentStatus">true</item>
windowTranslucentStatus
hará que la barra de estado sea transparentewindowDrawsSystemBarBackgrounds
le dice a la barra de estado que dibuje cualquier cosa debajo de ella en lugar de ser un vacío negro.Llama
DrawerLayout.setStatusBarBackground()
oDrawerLayout.setStatusBarBackgroundColor()
en tu actividad principalEsto le dice a DrawerLayout que coloree el área de la barra de estado.
fuente
Las anteriores son buenas soluciones, pero no funcionaron en mi caso,
mi caso: la barra de estado tiene un conjunto de color amarillo que ya usa estilos, no es translúcido. y el color de mi cajón de navegación es blanco, ahora cada vez que dibujo mi cajón de navegación siempre está detrás de la barra de estado y la barra de navegación también, ya que el color de la barra de navegación también está configurado.
Objetivo: cambiar la barra de estado y el color de la barra de navegación cuando se abre el cajón de navegación y restaurarlo cuando se cierra.
solucion:
binding.drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() { @Override public void onDrawerSlide(@NonNull View drawerView, float slideOffset) { } @Override public void onDrawerOpened(@NonNull View drawerView) { getWindow().setStatusBarColor(getResources().getColor(R.color.forground)); getWindow().setNavigationBarColor(getResources().getColor(R.color.forground)); } @Override public void onDrawerClosed(@NonNull View drawerView) { getWindow().setStatusBarColor(getResources().getColor(R.color.yellow)); getWindow().setNavigationBarColor(getResources().getColor(R.color.yellow)); } @Override public void onDrawerStateChanged(int newState) { } });
fuente
Todas las respuestas aquí son muy complicadas, déjame darte un código simple y directo. En su estilo AppTheme, agregue esta línea de código y obtendrá una barra de estado gris semitransparente cuando abra el cajón.
<item name="android:windowTranslucentStatus">true</item>
esto hará que funcione.
fuente