¿Cómo uso DrawerLayout para mostrar sobre la barra de acciones / barra de herramientas y debajo de la barra de estado?

394

He visto en la nueva especificación Side Nav de diseño de material que puede mostrar el cajón sobre la barra de acción y detrás de la barra de estado. ¿Cómo puedo implementar esto?

Chris Banes
fuente
44
Incluso hoy no hay una respuesta clara que funcione con compatibilidad con versiones anteriores. Este tipo de problemas realmente exaspera a cualquier programador. Ya promocionamos la API "N" y muchos aspectos básicos para mejorar en el sistema Android.
Val Martinez

Respuestas:

528

La nueva funcionalidad en el marco y las bibliotecas de soporte permiten exactamente esto. Hay tres 'piezas del rompecabezas':

  1. Usando la barra de herramientas para que puedas insertar tu barra de acción en tu jerarquía de vistas.
  2. Hacer DrawerLayout fitsSystemWindows para que se coloque detrás de las barras del sistema.
  3. Deshabilitar Theme.Materialel color normal de la barra de estado para que DrawerLayout pueda dibujar allí.

Asumiré que usará la nueva aplicacióncompat.

Primero, su diseño debería verse así:

<!-- The important thing to note here is the added fitSystemWindows -->
<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">

    <!-- Your normal content view -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- We use a Toolbar so that our drawer can be displayed
             in front of the action bar -->
        <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="?attr/colorPrimary" />

        <!-- The rest of your content view -->

    </LinearLayout>

    <!-- Your drawer view. This can be any view, LinearLayout
         is just an example. As we have set fitSystemWindows=true
         this will be displayed under the status bar. -->
    <LinearLayout
        android:layout_width="304dp"
        android:layout_height="match_parent"
        android:layout_gravity="left|start"
        android:fitsSystemWindows="true">

        <!-- Your drawer content -->

    </LinearLayout>

</android.support.v4.widget.DrawerLayout>

Luego en tu Actividad / Fragmento:

public void onCreate(Bundled savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Your normal setup. Blah blah ...

    // As we're using a Toolbar, we should retrieve it and set it
    // to be our ActionBar
    Toolbar toolbar = (...) findViewById(R.id.my_awesome_toolbar);
    setSupportActionBar(toolbar);

    // Now retrieve the DrawerLayout so that we can set the status bar color.
    // This only takes effect on Lollipop, or when using translucentStatusBar
    // on KitKat.
    DrawerLayout drawerLayout = (...) findViewById(R.id.my_drawer_layout);
    drawerLayout.setStatusBarBackgroundColor(yourChosenColor);
}

Luego debe asegurarse de que DrawerLayout esté visible detrás de la barra de estado. Lo haces cambiando tu tema de valores-v21:

values-v21 / themes.xml

<style name="Theme.MyApp" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>

Nota: Si <fragment android:name="fragments.NavigationDrawerFragment">se usa a en lugar de

<LinearLayout
    android:layout_width="304dp"
    android:layout_height="match_parent"
    android:layout_gravity="left|start"
    android:fitsSystemWindows="true">

    <!-- Your drawer content -->

</LinearLayout>

el diseño real, el efecto deseado se logrará si llama fitsSystemWindows(boolean)a una vista que regresa del onCreateViewmétodo.

@Override
public View onCreateView(LayoutInflater inflater, 
                         ViewGroup container,
                         Bundle savedInstanceState) {
    View mDrawerListView = inflater.inflate(
        R.layout.fragment_navigation_drawer, container, false);
    mDrawerListView.setFitsSystemWindows(true);
    return mDrawerListView;
}
Chris Banes
fuente
3
Sí, es DrawerLayoutnecesario que se coloque detrás de las barras del sistema. Luego debe configurarlo en la vista del cajón para que DrawerLayoutquede dentro de las ventanas.
Chris Banes
11
No puedo hacer que esto funcione en absoluto. Con el código anterior en una nueva aplicación de demostración, el resultado es similar a lo que describe @ScootrNova. Ver esta captura de
Michael Schmidt
66
Parece que realmente necesitas usar un negativo layout_marginTopen la raíz del diseño del contenido de tu cajón. De lo contrario, el fondo del diseño del contenido de su cajón se dibujará en la parte superior de la barra de estado, y todo lo demás se desplazará hacia abajo. Sin embargo, esto parece una solución un poco asquerosa, por lo que sé, no hay? Attr / statusBarSize o algo así como el proporcionado por Android.
Charles Madere
26
Para obtener el efecto donde el cajón es visible a través de la barra de estado, terminé configurando android: fitsSystemWindows en falso en DrawerLayout, android: fitsSystemWindows en verdadero en mi diseño de contenido principal (el diseño que contiene la barra de herramientas) y agregando <nombre del elemento = "android: windowTranslucentStatus"> verdadero </item> a mi tema - en Lollipop que es
Jakob
8
Esta respuesta es incompleta. También debe envolver su cajón de navegación dentro de un ScrimLayout. Ver stackoverflow.com/a/26926998/174149
Markus Hola
138

EDITAR: La nueva Biblioteca de soporte de diseño lo admite y ya no se requiere el método anterior.

Esto ahora se puede lograr utilizando la nueva Biblioteca de soporte de diseño de Android .

Puede ver la aplicación de ejemplo Cheesesquare de Chris Banes que muestra todas las nuevas características.


Método anterior:

Como no hay una solución completa publicada, esta es la forma en que logré el resultado deseado.

Primero incluya un ScrimInsetsFrameLayout en su proyecto.

/*
* 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 cree un estilo para que insetForegroundse pueda configurar.

valores / attrs.xml

<declare-styleable name="ScrimInsetsView">
    <attr name="insetForeground" format="reference|color" />
</declare-styleable>

Actualice el archivo xml de su actividad y asegúrese de que android:fitsSystemWindowsesté establecido en verdadero tanto en el DrawerLayoutcomo en el ScrimInsetsFrameLayout.

layout / activity_main.xml

<android.support.v4.widget.DrawerLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <!-- The main content view -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- Your main content -->

    </LinearLayout>

    <!-- The navigation drawer -->
    <com.example.app.util.ScrimInsetsFrameLayout 
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/scrimInsetsFrameLayout"
        android:layout_width="320dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/white"
        android:elevation="10dp"
        android:fitsSystemWindows="true"
        app:insetForeground="#4000">

        <!-- Your drawer content -->

    </com.example.app.util.ScrimInsetsFrameLayout>

</android.support.v4.widget.DrawerLayout>

Dentro del método onCreate de su actividad, configure el color de fondo de la barra de estado en el diseño del cajón.

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // ...

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
    mDrawerLayout.setStatusBarBackgroundColor(
        getResources().getColor(R.color.primary_dark));
}

Finalmente actualice el tema de su aplicación para que DrawerLayoutesté detrás de la barra de estado.

values-v21 / styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

Resultado:

Suyash
fuente
10
Esto funcionó mejor para mí. Pasé 2 días para que esto funcionara y este es el indicado. Esto debería estar marcado como Respuesta. Muchas gracias.
kalehv
2
No estoy usando appcompat y esto no funcionó. :( ¿Hay alguna guía para que esto funcione sin appcompat?
Jared Rummler
3
Esta es la respuesta más perfecta. Lo he implementado y probado en varios dispositivos Android desde 4.X a 5.X y puedo confirmar que funciona perfectamente. Muchas gracias.
Aritra Roy
2
Como dije, funciona perfectamente, pero tengo un pequeño problema. La actividad con el cajón de navegación tiene la barra de estado transparente, pero todas las demás actividades han perdido el color "primario" de la barra de estado. ¿Cómo recuperar eso?
Aritra Roy
55
Me tomó tres días aceptar que actualmente no hay otra forma que usar este diseño adicional envuelto alrededor del fragmento del cajón. De lo contrario, la barra de estado será gris (color de fondo del primer hijo) o el cajón se mostrará debajo de la barra de estado.
Denis Loh
96

Con el lanzamiento de la última biblioteca de soporte de Android (rev 22.2.0) tenemos una biblioteca de soporte de diseño y, como parte de esto, una nueva vista llamada NavigationView . Entonces, en lugar de hacer todo por nuestra cuenta con ScrimInsetsFrameLayouttodo lo demás, simplemente usamos esta vista y todo se hace por nosotros.

Ejemplo

Paso 1

Agregue el Design Support Librarya su build.gradlearchivo

dependencies {
    // Other dependencies like appcompat
    compile 'com.android.support:design:22.2.0'
}

Paso 2

Agregue el NavigationViewa su DrawerLayout:

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

     <!-- Your contents -->

     <android.support.design.widget.NavigationView
         android:id="@+id/navigation"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_gravity="start"
         app:menu="@menu/navigation_items" /> <!-- The items to display -->
 </android.support.v4.widget.DrawerLayout>

Paso 3

Cree un nuevo recurso de menú /res/menuy agregue los elementos e íconos que desea mostrar:

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@drawable/ic_action_home"
            android:title="Home" />
        <item
            android:id="@+id/nav_example_item_1"
            android:icon="@drawable/ic_action_dashboard"
            android:title="Example Item #1" />
    </group>

    <item android:title="Sub items">
        <menu>
            <item
                android:id="@+id/nav_example_sub_item_1"
                android:title="Example Sub Item #1" />
        </menu>
    </item>

</menu>

Paso 4

Inicie el NavigationView y maneje los eventos de clic:

public class MainActivity extends AppCompatActivity {

    NavigationView mNavigationView;
    DrawerLayout mDrawerLayout;

    // Other stuff

    private void init() {
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                mDrawerLayout.closeDrawers();
                menuItem.setChecked(true);
                switch (menuItem.getItemId()) {
                    case R.id.nav_home:
                        // TODO - Do something
                        break;
                    // TODO - Handle other items
                }
                return true;
            }
        });
    }
}

Paso 5

Asegúrese de configurar android:windowDrawsSystemBarBackgroundsy android:statusBarColorde lo values-v21contrario su cajón no se mostrará "debajo" de la barra de estado

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Other attributes like colorPrimary, colorAccent etc. -->
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

Paso opcional

Agregue un encabezado a NavigationView. Para esto, simplemente cree un nuevo diseño y agréguelo app:headerLayout="@layout/my_header_layout"a NavigationView.

Resultado

imagen que muestra la vista de navegación

Notas

  • El color resaltado usa el color definido a través del colorPrimaryatributo
  • Los elementos de la lista usan el color definido a través del textColorPrimaryatributo
  • Los iconos usan el color definido a través del textColorSecondaryatributo

También puede consultar la aplicación de ejemplo de Chris Banes que resalta NavigationView junto con otras vistas nuevas que forman parte de la Biblioteca de soporte de diseño (como FloatingActionButton , TextInputLayout , Snackbar , TabLayout , etc.)

contrarrestar
fuente
1
gracias @reVerse !!. > Si desea actualizar cada elemento e ícono en la lista de los archivos de estilo, puede hacerlo usando:<item name="itemTextColor">@color/YOUR_COLOR</item> <item name="itemIconTint">@color/YOUR_COLOR</item>
Juan Saravia
¿Cómo se cambia el color de fondo del elemento seleccionado?
Joop
2
Este enfoque aún produce NavigationView que está detrás de ActionBar.
southerton el
1
@southerton, por supuesto, tienes que usar un Toolbar- no hay forma de hacer esto con unActionBar
reVerse
1
@ reegan29 Simplemente llame a mDrawerLayout.openDrawer(GravityCompat.START);donde quiera. Si está utilizando un, ActionBarDrawerToggleesto debe hacerse automáticamente tan pronto como haga clic en el icono de hamburguesa.
reVerse
6

Haz que funcione, en los valores-v21 estilos o tema xml necesita usar este atributo:

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

Eso hace la magia!

Nicolas Jafelle
fuente
3
Esto hace que mi barra de acción aparezca detrás de la barra de estado también.
Michiel
Pero ese es el efecto que estamos tratando de lograr, mira la aplicación Gmail 5.0. Muestra la barra lateral detrás de la barra de estado.
Nicolas Jafelle
Eso no es lo que quise decir. Aunque el cajón de navegación está detrás de la barra de estado con esta línea de código, también lo está la barra de herramientas / barra de acción.
Michiel
2
El afiche y el que responde es un empleado de Google que diseñó AppCompat, por lo que estoy bastante seguro de que sabía lo que estaba haciendo cuando escribió el contenido.
afollestad
@Mixx, puede configurar android: fitsSystemWindows = "true" para su vista de contenido normal (si se toma el diseño de respuesta aceptado, por ejemplo). Puede funcionar, incluso para Android 4.4. Pero hay una ligera diferencia aquí: en Android 5.0 el nivel de transparencia en la barra de estado es algo mayor (valor alfa más alto) que en GMail, lo que hace que la barra de estado sea aún más oscura.
Qianqian
6

Los enfoques anteriores son correctos y pueden estar funcionando. He creado una demostración funcional siguiendo la guía anterior y probé en 2.xa 5.x

Puedes clonar desde Github

Lo importante para jugar es en Actividad principal

toolbar = (Toolbar) findViewById(R.id.toolbar);
res = this.getResources();

this.setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    ScrimInsetsFrameLayout scrimInsetsFrameLayout = (ScrimInsetsFrameLayout)
            findViewById(R.id.linearLayout);
    scrimInsetsFrameLayout.setOnInsetsCallback(this);
} 

y la llamada de vuelta

@Override
public void onInsetsChanged(Rect insets) {
    Toolbar toolbar = this.toolbar;
    ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)
        toolbar.getLayoutParams();
    lp.topMargin = insets.top;
    int top = insets.top;
    insets.top += toolbar.getHeight();
    toolbar.setLayoutParams(lp);
    insets.top = top; // revert
}

Absolutamente el tema para V21 hace la magia

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- API 21 theme customizations can go here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/accent_material_light</item>
    <item name="windowActionModeOverlay">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>

y el ScrimInsetsFrameLayout

Ahora esto es más fácil con la nueva biblioteca de soporte de diseño

compile 'com.android.support:design:22.2.0'

clon de @Chris Banes https://github.com/chrisbanes/cheesesquare

Vipin Sahu
fuente
4

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

Ahora, cuando cierre el cajón, debe cambiar el color de la barra de estado nuevamente a oscuro, para que pueda hacerlo de esta manera.

        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 tu cajón se verá así

            <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á así

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

Harry Sharma
fuente
Alternativamente, si está utilizando una vista personalizada en ActionBar, puede establecer la visibilidad de la vista personalizada como INVISIBLE en onDrawerSlide () y VISIBLE en onDrawerClosed ().
Milán
3

Estoy usando la biblioteca de soporte de diseño. Y con solo usar un tema personalizado, logré una barra de estado transparente cuando abrí el cajón de navegación.

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

<style name="NavigationStyle" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/primaryColor</item>
    <item name="colorPrimaryDark">@color/primaryColorDark</item>

    <!-- To Make Navigation Drawer Fill Status Bar and become Transparent Too -->
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>

</style>

Finalmente agregue el tema en el archivo de manifiesto

<activity
  ........
  ........
 android:theme="@style/NavigationStyle"> 
</activity>

No olvides usar la propiedad, android:fitsSystemWindows="true"en "DrawerLayout"

katwal-Dipak
fuente
1
¿Cómo usar esto para dispositivos de nivel 19 de API?
AndroidGuy
2

Este es el más simple, y funcionó para mí:

En los valores-21:

<resources>
    <style name="AppTheme" parent="AppTheme.Base">
        ...
        <item name="android:windowTranslucentStatus">true</item>
    </style>
    <dimen name="topMargin">25dp</dimen>
</resources>

En los valores:

<resources>
    <dimen name="topMargin">0dp</dimen>
</resources>

Y configúralo en tu barra de herramientas

android:layout_marginTop="@dimen/topMargin"
Nicolás López
fuente
También hice esto, y funcionó a las mil maravillas en Lollipop. Pero solía 24dppara el margen superior.
Rafa
Cuando divide la pantalla en dispositivos con Android 7.1, puede ver esta brecha en la parte superior si su aplicación es la segunda parte de la pantalla.
Cícero Moura el
1

En lugar de usar el ScrimInsetsFrameLayout... ¿No es más fácil agregar una vista con una altura fija 24dpy un fondo de primaryColor?

Entiendo que esto implica agregar una vista ficticia en la jerarquía, pero me parece más limpia.

Ya lo probé y está funcionando bien.

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_base_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- THIS IS THE VIEW I'M TALKING ABOUT... -->
        <View
            android:layout_width="match_parent"
            android:layout_height="24dp"
            android:background="?attr/colorPrimary" />

        <android.support.v7.widget.Toolbar
            android:id="@+id/activity_base_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:elevation="2dp"
            android:theme="@style/ThemeOverlay.AppCompat.Dark" />

        <FrameLayout
            android:id="@+id/activity_base_content_frame_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>

    <fragment
        android:id="@+id/activity_base_drawer_fragment"
        android:name="com.myapp.drawer.ui.DrawerFragment"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:elevation="4dp"
        tools:layout="@layout/fragment_drawer" />

</android.support.v4.widget.DrawerLayout>
mato
fuente
Cuando divide la pantalla en dispositivos con Android 7.1, puede ver esta brecha en la parte superior si su aplicación es la segunda parte de la pantalla.
Cícero Moura el
0

Prueba con esto:

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


<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--Main layout and ads-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <FrameLayout
            android:id="@+id/ll_main_hero"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">

        </FrameLayout>

        <FrameLayout
            android:id="@+id/ll_ads"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <View
                android:layout_width="320dp"
                android:layout_height="50dp"
                android:layout_gravity="center"
                android:background="#ff00ff" />
        </FrameLayout>


    </LinearLayout>

    <!--Toolbar-->
    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/toolbar"
        android:elevation="4dp" />
</FrameLayout>


<!--left-->
<ListView
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:choiceMode="singleChoice"
    android:divider="@null"
    android:background="@mipmap/layer_image"
    android:id="@+id/left_drawer"></ListView>

<!--right-->
<FrameLayout
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="right"
    android:background="@mipmap/layer_image">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/ken2"
        android:scaleType="centerCrop" />
</FrameLayout>

estilo:

<style name="ts_theme_overlay" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/red_A700</item>
    <item name="colorPrimaryDark">@color/red1</item>
    <item name="android:windowBackground">@color/blue_A400</item>
</style>

La actividad principal extiende ActionBarActivity

toolBar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolBar);

Ahora puedes onCreateOptionsMenuusar ActionBar con ToolBar como siempre.

Este es mi diseño

  • SUPERIOR: Cajón izquierdo - Cajón derecho
    • MID: ToolBar (ActionBar)
    • ABAJO: ListFragment

¡Espero que lo entiendas! ¡Diviértete!

Son Nguyen Thanh
fuente