Comment utiliser DrawerLayout pour afficher sur l'ActionBar / Toolbar et sous la barre d'état?

394

J'ai vu dans la nouvelle conception de matériaux Side Nav spec que vous pouvez afficher le tiroir sur la barre d'action et derrière la barre d'état. Comment puis-je implémenter cela?

Chris Banes
la source
4
Même aujourd'hui, il n'y a pas de réponse claire qui fonctionne avec la compatibilité descendante. Ce genre de problèmes exaspère vraiment tout programmeur. Déjà la promotion de l'API "N" et de nombreux aspects de base à améliorer dans le système Android.
Val Martinez

Réponses:

528

De nouvelles fonctionnalités dans le cadre et les bibliothèques de support permettent exactement cela. Il y a trois «pièces du puzzle»:

  1. Utilisation de la barre d'outils afin que vous puissiez intégrer votre barre d'actions dans votre hiérarchie de vues.
  2. Création de DrawerLayout fitsSystemWindows pour qu'il soit disposé derrière les barres système.
  3. Désactiver Theme.Materialla coloration normale de la barre d'état pour que DrawerLayout puisse y dessiner à la place.

Je suppose que vous utiliserez la nouvelle application compatible.

Tout d'abord, votre mise en page devrait ressembler à ceci:

<!-- 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>

Puis dans votre activité / fragment:

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);
}

Ensuite, vous devez vous assurer que le DrawerLayout est visible derrière la barre d'état. Pour ce faire, vous changez votre thème valeurs-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>

Remarque: si un <fragment android:name="fragments.NavigationDrawerFragment">est utilisé au lieu de

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

    <!-- Your drawer content -->

</LinearLayout>

la disposition réelle, l'effet souhaité sera obtenu si vous appelez fitsSystemWindows(boolean)une vue que vous revenez de la onCreateViewméthode.

@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
la source
3
Oui, DrawerLayoutil doit être disposé derrière les barres du système. Vous devez ensuite le définir sur la vue du tiroir afin de DrawerLayoutle disposer dans les encarts de fenêtre.
Chris Banes
11
Je ne peux pas faire fonctionner ça du tout. Avec le code ci-dessus dans une nouvelle application de démonstration, le résultat ressemble à ce que décrit @ScootrNova. Voir cette capture d'écran: imgur.com/QLk3syt
Michael Schmidt
6
Il semble que vous ayez réellement besoin d'utiliser un négatif layout_marginTopdans la racine de la disposition de votre contenu de tiroir. Sinon, l'arrière-plan de la disposition du contenu de votre tiroir sera dessiné en haut de la barre d'état, et tout le reste sera poussé vers le bas. Cela semble cependant être une solution un peu grossière, pour autant que je sache, il n'y a pas? Attr / statusBarSize ou quelque chose comme ça fourni par Android.
Charles Madere
26
Pour obtenir l'effet où le tiroir est visible à travers la barre d'état, j'ai fini par définir android: fitsSystemWindows sur false dans DrawerLayout, android: fitsSystemWindows sur true dans ma disposition de contenu principale (la disposition contenant la barre d'outils) et en ajoutant <nom de l'élément = "android: windowTranslucentStatus"> true </item> à mon thème - sur Lollipop c'est-à-dire
Jakob
8
Cette réponse est incomplète. Vous devez également envelopper votre tiroir de navigation dans un ScrimLayout. Voir stackoverflow.com/a/26926998/174149
Markus Hi
138

EDIT: la nouvelle bibliothèque de support de conception prend en charge cela et la méthode précédente n'est plus nécessaire.

Cela peut maintenant être réalisé en utilisant la nouvelle bibliothèque de support de conception Android .

Vous pouvez voir l' exemple d'application Cheesesquare de Chris Banes qui présente toutes les nouvelles fonctionnalités.


Méthode précédente:

Puisqu'il n'y a pas de solution complète publiée, voici comment j'ai obtenu le résultat souhaité.

Incluez d' abord un ScrimInsetsFrameLayout dans votre projet.

/*
* 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);
    }
}

Ensuite, créez un styleable afin que le insetForegroundpuisse être réglé.

values ​​/ attrs.xml

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

Mettre à jour le fichier xml de votre activité et assurez - vous android:fitsSystemWindowsest fixé à vrai sur les deux DrawerLayout, ainsi que le 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>

Dans la méthode onCreate de votre activité, définissez la couleur d'arrière-plan de la barre d'état sur la disposition du tiroir.

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));
}

Enfin, mettez à jour le thème de votre application pour que le DrawerLayoutsoit derrière la barre d'état.

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>

Résultat:

Suyash
la source
10
Cela a fonctionné le mieux pour moi. J'ai passé 2 jours pour faire fonctionner cette chose et c'est celle-là. Cela devrait être marqué comme réponse. Merci beaucoup.
kalehv
2
Je n'utilise pas appcompat et cela n'a pas fonctionné. :( Y a-t-il un guide pour que cela fonctionne sans compatibilité avec les applications?
Jared Rummler
3
C'est la réponse la plus parfaite. Je l'ai implémenté et testé sur divers appareils Android de 4.X à 5.X et je peux confirmer qu'il fonctionne parfaitement. Merci beaucoup.
Aritra Roy
2
Comme je l'ai dit, cela fonctionne parfaitement, mais j'ai un petit problème. L'activité avec le tiroir de navigation a la barre d'état transparente, mais toutes les autres activités ont perdu la couleur "primaryDark" de la barre d'état. Comment récupérer ça?
Aritra Roy
5
Il m'a fallu trois jours pour accepter qu'il n'y a actuellement aucun autre moyen que d'utiliser cette disposition supplémentaire enroulée autour du fragment de tiroir. Sinon, la barre d'état sera grise (couleur d'arrière-plan du premier enfant) ou le tiroir sera affiché sous la barre d'état.
Denis Loh
96

Avec la sortie de la dernière bibliothèque de support Android (rev 22.2.0), nous avons une bibliothèque de support de conception et dans le cadre de cette nouvelle vue appelée NavigationView . Donc, au lieu de tout faire par nous-mêmes avec ScrimInsetsFrameLayouttoutes les autres choses, nous utilisons simplement cette vue et tout est fait pour nous.

Exemple

Étape 1

Ajoutez le Design Support Libraryà votre build.gradlefichier

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

Étape 2

Ajoutez le NavigationViewà votre 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>

Étape 3

Créez une nouvelle ressource de menu dans /res/menuet ajoutez les éléments et les icônes que vous souhaitez afficher:

<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>

Étape 4

Initiez la NavigationView et gérez les événements 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;
            }
        });
    }
}

Étape 5

Assurez - vous de jeu android:windowDrawsSystemBarBackgroundset android:statusBarColordans values-v21sinon votre tiroir s'affiche gagné le `t « sous » la barre d' état

<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>

Étape facultative

Ajoutez un en-tête à NavigationView. Pour cela, créez simplement une nouvelle mise en page et ajoutez-la app:headerLayout="@layout/my_header_layout"à NavigationView.

Résultat

image montrant la vue de navigation

Remarques

  • La couleur en surbrillance utilise la couleur définie via l' colorPrimaryattribut
  • Les éléments de liste utilisent la couleur définie via l' textColorPrimaryattribut
  • Les icônes utilisent la couleur définie via l' textColorSecondaryattribut

Vous pouvez également consulter l' exemple d'application de Chris Banes qui met en évidence la NavigationView ainsi que les autres nouvelles vues qui font partie de la bibliothèque de support de conception (comme FloatingActionButton , TextInputLayout , Snackbar , TabLayout etc.)

inverser
la source
1
merci @reVerse !!. > Si vous souhaitez mettre à jour chaque élément et icône de la liste à partir des fichiers de style, vous pouvez le faire en utilisant:<item name="itemTextColor">@color/YOUR_COLOR</item> <item name="itemIconTint">@color/YOUR_COLOR</item>
Juan Saravia
Comment changez-vous la couleur d'arrière-plan de l'élément sélectionné?
Joop
2
Cette approche produit toujours le NavigationView qui se trouve derrière l'ActionBar.
Southerton
1
@southerton bien sûr, vous devez utiliser un Toolbar- il n'y a aucun moyen de le faire avec unActionBar
reVerse
1
@ reegan29 Appelez simplement mDrawerLayout.openDrawer(GravityCompat.START);où vous voulez. Si vous utilisez un, ActionBarDrawerTogglecela devrait être fait automatiquement dès que vous cliquez sur l'icône du hamburger.
inversez
6

Faites-le fonctionner, dans les styles values-v21 ou le thème xml doit utiliser cet attribut:

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

Ça fait la magie!

Nicolas Jafelle
la source
3
Cela fait également apparaître ma barre d'action derrière la barre d'état.
Michiel
Mais c'est l'effet que nous essayons d'obtenir, regardez l'application Gmail 5.0? Il montre la barre latérale derrière la barre d'état.
Nicolas Jafelle
Ce n'est pas ce que je voulais dire. Même si le tiroir de navigation se trouve derrière la barre d'état avec cette ligne de code, la barre d'outils / barre d'action l'est également.
Michiel
2
L'affiche et le répondeur sont un employé de Google qui a conçu AppCompat, donc je suis sûr qu'il savait ce qu'il faisait lorsqu'il a écrit le contenu.
afollestad
@Mixx, vous pouvez définir android: fitsSystemWindows = "true" pour votre affichage de contenu normal (si pris la disposition de réponse acceptée par exemple). Cela peut fonctionner, même pour Android 4.4. Mais il y a une légère différence ici: dans Android 5.0, le niveau de transparence sur la barre d'état est un peu plus élevé (valeur alpha plus élevée) que dans GMail, ce qui rend la barre d'état encore plus sombre.
Qianqian
6

Les approches ci-dessus sont correctes et peuvent fonctionner. J'ai créé une démo fonctionnelle en suivant le guide ci-dessus et testé sur 2.x à 5.x

Vous pouvez cloner à partir de Github

La chose importante à jouer est dans l'activité principale

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);
} 

et le rappel

@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
}

Absolument le thème pour V21 fait la magie

<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>

et ScrimInsetsFrameLayout

Maintenant, cela devient plus facile avec la nouvelle bibliothèque de support de conception

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

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

Vipin Sahu
la source
4

Toutes les réponses mentionnées ici sont trop anciennes et trop longues. La meilleure et courte solution qui fonctionne avec la dernière Navigationview est

@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);

    }
}

cela va changer la couleur de votre barre d'état en transparent lorsque vous ouvrez le tiroir

Maintenant, lorsque vous fermez le tiroir, vous devez à nouveau changer la couleur de la barre d'état en sombre, vous pouvez donc le faire de cette façon.

        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);
                    }
                    }

puis dans la mise en page principale, ajoutez une seule ligne ie

            android:fitsSystemWindows="true"

et la disposition de votre tiroir ressemblera

            <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">

et votre vue de navigation ressemblera

    <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"
        />

Je l'ai testé et il fonctionne pleinement.J'espère qu'il aide quelqu'un.Ce n'est peut-être pas la meilleure approche, mais cela fonctionne bien et est simple à mettre en œuvre. Marquez-le si cela vous aide.Codage heureux :)

Harry Sharma
la source
Si vous utilisez une vue personnalisée dans ActionBar, vous pouvez également définir la visibilité de la vue personnalisée sur INVISIBLE dans onDrawerSlide () et sur VISIBLE dans onDrawerClosed ().
Milan
3

J'utilise la bibliothèque de support de conception. Et juste en utilisant un thème personnalisé, j'ai réalisé une barre d'état transparente lors de l'ouverture du tiroir de navigation.

entrez la description de l'image ici

entrez la description de l'image ici

<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>

Enfin ajouter un thème dans le fichier manifeste

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

N'oubliez pas d'utiliser la propriété, android:fitsSystemWindows="true"dans "DrawerLayout"

katwal-Dipak
la source
1
comment l'utiliser pour les appareils de niveau api 19?
AndroidGuy
2

C'est le plus simple, et cela a fonctionné pour moi:

Dans les valeurs-21:

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

Dans les valeurs:

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

Et réglez sur votre barre d'outils

android:layout_marginTop="@dimen/topMargin"
Nicolás López
la source
J'ai aussi fait ça, et ça a fonctionné comme un charme sur Lollipop. Mais j'ai utilisé 24dppour la marge supérieure.
Rafa
Lorsque vous divisez l'écran sur les appareils avec Android 7.1, vous pouvez voir cet écart en haut si votre application est la deuxième partie de l'écran.
Cícero Moura
1

Au lieu d'utiliser le ScrimInsetsFrameLayout... N'est-il pas plus facile d'ajouter simplement une vue avec une hauteur fixe 24dpet un arrière-plan de primaryColor?

Je comprends que cela implique l'ajout d'une vue factice dans la hiérarchie, mais cela me semble plus propre.

Je l'ai déjà essayé et ça marche 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
la source
Lorsque vous divisez l'écran sur les appareils avec Android 7.1, vous pouvez voir cet écart en haut si votre application est la deuxième partie de l'écran.
Cícero Moura
0

Essayez avec ceci:

<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>

style:

<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>

L'activité principale étend ActionBarActivity

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

Maintenant, vous pouvez onCreateOptionsMenuaimer comme ActionBar normal avec ToolBar.

Ceci est ma mise en page

  • HAUT: Tiroir gauche - Tiroir droit
    • MID: ToolBar (ActionBar)
    • EN BAS: ListFragment

J'espère que vous comprenez! Amusez-vous!

Son Nguyen Thanh
la source