Pregunta 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 el nuevo Material Design Spec y el Lista de verificación de diseño.
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 este ASI QUE publicar como se sugiere en el blog de desarrolladores de Google, enlace arriba ¿Cómo uso DrawerLayout para mostrar sobre la barra de herramientas / barra de herramientas y debajo de la barra de estado?.

A continuación está 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 está mi tema de 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 está mi tema de 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 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 hay un captura de pantalla de mi cajón de navegación que muestra la parte superior no es semi transparente

Screenshot showing non transparent over the status bar


76
2017-11-04 21:23


origen


Respuestas:


El fondo de la barra de estado es blanco, el fondo de su cajón LinearLayout. ¿Por qué? Usted es la configuración fitsSystemWindows="true" para tu DrawerLayout y el LinearLayout dentro de eso. Esto causa tu LinearLayout expandir detrás 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 colorea el fondo de tu contenido dentro de él. O

2) Puedes eliminar fitsSystemWindows="true" de tu 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 su cajón se extienda por detrás de la barra de estado y tenga una superposición semitransparente del tamaño de la barra de estado, puede usar un ScrimInsetFrameLayout como un contenedor para el contenido de su cajón (ListView) y establecer el fondo de la barra de estado usando app:insetForeground="#4000". Por supuesto, puedes cambiar #4000 a todo lo que quieras No te olvides de 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 a todo lo que quieras Sin embargo, ¡no olvide configurar el fondo de su contenido por separado!

EDITAR: Ya no necesitas lidiar con nada de esto. Por favor mira Biblioteca de soporte de diseño por una vez más fácil Cajón de navegación / Ver la implementación.


95
2017-11-14 14:27



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:

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

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


29
2017-11-05 20:52



¿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 android:background para poder mostrar 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.


15
2017-11-11 12:27



Debe envolver el diseño de su cajón de navegación dentro de un 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 tus ScrimLayout.

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

Más tarde anular onDraw dibujar un rectángulo semitransparente.

Un ejemplo la implementación se puede encontrar en la fuente de la aplicación Google IO. aquí puedes ver cómo se usa en el diseño xml.


8
2017-11-14 09:43



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 actualizan 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)}, 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 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>

6
2017-11-15 08:49



Tenía una característica similar para implementar en mi proyecto. Y para hacer que mi cajón sea transparente, solo uso el transparencia para 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:

     <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 eso puede ayudarte a entender los códigos alfa en colores hexadecimales.


4
2017-11-14 13:24



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

            <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. Marcado si ayuda. Codificación feliz :)


2
2018-02-12 12:28