Je travaille sur un projet Android et j'implémente le tiroir de navigation. Je lis les nouvelles spécifications de conception des matériaux et la liste de contrôle de conception des matériaux .
La spécification indique que le volet coulissant doit flotter au-dessus de tout le reste, y compris la barre d'état, et être semi-transparent sur la barre d'état.
Mon panneau de navigation est au-dessus de la barre d'état mais il n'a aucune transparence. J'ai suivi le code de ce message SO comme suggéré dans le blog des développeurs Google, lien ci-dessus Comment utiliser DrawerLayout pour afficher sur l'ActionBar / Toolbar et sous la barre d'état? .
Ci-dessous ma mise en page 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>
Ci-dessous est mon thème d'applications
<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>
Ci-dessous, le thème de mes applications 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>
Voici ma méthode 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);
}
Ci-dessous, une capture d' écran de mon tiroir de navigation montrant que le haut n'est pas semi-transparent
Réponses:
L'arrière-plan de votre barre d'état est blanc, l'arrière-plan de votre tiroir
LinearLayout
. Pourquoi? Vous êtes les paramètresfitsSystemWindows="true"
de votreDrawerLayout
et de l'LinearLayout
intérieur. Cela provoque votreLinearLayout
expansion derrière la barre d'état (qui est transparente). Ainsi, le fond du tiroir fait partie de la barre d'état blanc.Si vous ne voulez pas que votre tiroir s'étende derrière la barre d'état (vous voulez avoir un arrière-plan semi-transparent pour toute la barre d'état), vous pouvez faire deux choses:
1) Vous pouvez simplement supprimer n'importe quelle valeur d'arrière-plan de votre
LinearLayout
et colorer l'arrière-plan de votre contenu à l'intérieur. Ou2) Vous pouvez supprimer
fitsSystemWindows="true"
de votreLinearLayout
. Je pense que c'est une approche plus logique et plus propre. Vous éviterez également de projeter une ombre sous la barre d'état, là où votre tiroir de navigation ne s'étend pas.Si vous souhaitez que votre tiroir s'étende derrière la barre d'état et ait une superposition semi-transparente de la taille d'une barre d'état, vous pouvez utiliser a
ScrimInsetFrameLayout
comme conteneur pour le contenu de votre tiroir (ListView
) et définir l'arrière-plan de la barre d'état à l'aide deapp:insetForeground="#4000"
. Bien sûr, vous pouvez changer#4000
ce que vous voulez. N'oubliez pas de resterfitsSystemWindows="true"
ici!Ou si vous ne voulez pas superposer votre contenu et n'afficher qu'une couleur unie, vous pouvez simplement définir l'arrière-plan de votre
LinearLayout
comme vous le souhaitez. N'oubliez pas de définir l'arrière-plan de votre contenu séparément!EDIT: Vous n'avez plus besoin de faire face à tout cela. Veuillez consulter la bibliothèque de support de conception pour une implémentation de tiroir / vue de navigation plus facile.
la source
Tout ce que vous avez à faire est d'utiliser une couleur semi-transparente pour la barre d'état. Ajoutez ces lignes à votre thème v21:
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@color/desired_color</item>
N'oubliez pas que la
color
(ressource) doit toujours être au format#AARRGGBB
. Cela signifie que la couleur comprendra également la valeur alpha.la source
Pourquoi ne pas utiliser quelque chose de similaire?
<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>
Le code ci-dessus utilise la ressource alpha dans le
android:background
pour pouvoir afficher la transparence dans la barre d'actions.Il existe d'autres moyens de le faire via le code, comme le montrent d'autres réponses. Ma réponse ci-dessus, fait le nécessaire dans le fichier de mise en page xml, qui à mon avis est facilement éditable.
la source
Toutes les réponses mentionnées ici sont trop anciennes et trop longues. La meilleure solution courte 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 manière.
@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); } }
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 que cela 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 aide. Bon codage :)
la source
Vous devez envelopper la disposition de votre tiroir de navigation dans un
ScrimLayout
.A
ScrimLayout
dessine essentiellement un rectangle semi-transparent sur la disposition de votre tiroir de navigation. Pour récupérer la taille de l'encart, remplacez simplementfitSystemWindows
votre fichierScrimLayout
.@Override protected boolean fitSystemWindows(Rect insets) { mInsets = new Rect(insets); return true; }
Remplacement ultérieur
onDraw
pour dessiner un rectangle semi-transparent.Un exemple de mise en œuvre peut être trouvé dans la source de l'application Google IO. Ici vous pouvez voir comment il est utilisé dans la mise en page xml.
la source
Si vous voulez que le panneau de navigation se trouve sur la barre d'état et soit semi-transparent sur la barre d'état. Google I / O Android App Source fournit une bonne solution (les fichiers APK du Play Store ne sont pas mis à jour pour la dernière version)
Vous avez d'abord besoin d'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); } }
Ensuite, dans votre mise en page XML, modifiez cette partie
<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>
Remplacez LinearLayout par ScrimInsetFrameLayout comme ceci
<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>
la source
ScrimInsetsView_insetForeground
attribut.android.support.design.internal.ScrimInsetsFrameLayout
de la bibliothèque de supportJ'avais une fonctionnalité similaire à implémenter dans mon projet. Et pour rendre mon tiroir transparent, j'utilise simplement la transparence pour les couleurs hexagonales . En utilisant 6 chiffres hexadécimaux, vous avez 2 chiffres hexadécimaux pour chaque valeur de rouge, vert et bleu respectivement. mais si vous mettez deux chiffres supplémentaires (8 chiffres hexadécimaux), vous avez donc ARVB (deux chiffres pour la valeur alpha) ( Regardez ici ).
Voici les valeurs d'opacité hexadécimales: pour les 2 chiffres supplémentaires
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
Par exemple: si vous avez une couleur hexadécimale (# 111111), mettez simplement une des valeurs d'opacité pour obtenir la transparence. comme ceci: (# 11111100)
Mon tiroir ne recouvre pas la barre d'action (comme la vôtre) mais la transparence peut être appliquée dans ces cas également. Voici mon code:
<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>
Et voici un autre article qui peut vous aider à comprendre les codes alpha en couleurs hexadécimales.
la source
Les solutions existantes sont assez dépassées. Voici la dernière solution qui devrait fonctionner parfaitement sur AndroidX ou les bibliothèques de matériaux.
Ajoutez
android:fitsSystemWindows="true"
à la racine la vue de votre mise en page, qui se trouve être DrawerLayout pour votre cas.Cela indique à la vue d'utiliser la totalité de l'écran pour la mesure et la mise en page, chevauchant la barre d'état.
Ajoutez ce qui suit à votre style XML
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowTranslucentStatus">true</item>
windowTranslucentStatus
rendra la barre d'état transparentewindowDrawsSystemBarBackgrounds
dit à la barre d'état de dessiner n'importe quoi en dessous au lieu d'être un vide noir.Appelez
DrawerLayout.setStatusBarBackground()
ouDrawerLayout.setStatusBarBackgroundColor()
dans votre activité principaleCela indique à DrawerLayout de colorer la zone de la barre d'état.
la source
Au-dessus des bonnes solutions, mais elles n'ont pas fonctionné dans mon cas,
mon cas : barre d'état a déjà une couleur jaune en utilisant des styles, elle n'est pas translucide. et la couleur de mon tiroir de navigation est blanche, maintenant chaque fois que je dessine mon tiroir de navigation, il est toujours derrière la barre d'état et la barre de navigation, car la couleur de la barre de navigation est également définie.
objectif : modifier la barre d'état et la couleur de la barre de navigation lorsque le tiroir de navigation est ouvert et le restaurer lorsqu'il est fermé.
Solution :
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) { } });
la source
Toutes les réponses ici sont très compliquées, laissez-moi vous donner un code simple et direct. Sous votre style AppTheme, ajoutez cette ligne de code et vous obtiendrez une barre d'état grise semi-transparente lorsque vous ouvrirez le tiroir.
<item name="android:windowTranslucentStatus">true</item>
cela le fera fonctionner.
la source