J'étais vraiment content quand BottomNavigationView est sorti il y a une semaine mais je suis confronté à des problèmes qui ne me permettent pas de le résoudre, comme voir une ombre sur BottomNavigationView, de la même manière que Google Photos Android L'application nous montre:
Si nous tapons sur un élément du menu Google Photos, nous pouvons voir un effet d'entraînement qui est teinté en bleu comme l'icône et la couleur du texte (lorsqu'elle est sélectionnée).
La mise en œuvre de la solution fournie par Google uniquement affiche une couleur d'effet d'ondulation grise, et pire, elle ne s'affiche pas lorsque nous modifions la couleur d'arrière-plan de la vue de navigation inférieure (design:itemBackground="..."
).
Quelqu'un sait comment le résoudre?
Voici ce que j'ai réalisé:
effet d'entraînement + gif d'élévation
J'ai créé une démo sur GitHub pour vous aider.
Tout d'abord, utilisez la dernière bibliothèque de support compile "com.Android.support:design:$SUPPORT_VERSION"
Cela ne fonctionne que si vous définissez la couleur d'arrière-plan blanc Android:background="@Android:color/white"
Notez que l'effet d'entraînement disparaîtra si vous utilisez app:itemBackground
propriété ou dans votre cas c'est design:itemBackground="..."
, il suffit donc de le supprimer.
<Android.support.design.widget.BottomNavigationView
Android:id="@+id/bottom_navigation"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_alignParentBottom="true"
Android:background="@Android:color/white"
app:elevation="16dp"
app:itemIconTint="@drawable/nav_item_color_state"
app:itemTextColor="@drawable/nav_item_color_state"
app:menu="@menu/bottom_navigation_main" />
Gestion de l'état activé/désactivé:
Vous devez créer un fichier de sélection:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_checked="true" Android:color="@color/colorPrimary" />
<item Android:color="@Android:color/darker_gray" />
</selector>
Si vous souhaitez modifier l'effet d'ondulation gris standard, modifiez la propriété colorControlHighlight
dans AppTheme afin qu'elle ressemble à ceci:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="colorControlHighlight">@color/colorPrimaryRipple</item>
</style>
Utilisez 26% d'alpha pour les ondulations colorées.
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryRipple">#423F51B5</color>
app:elevation="8dp"
.app:itemBackground
Et mettre Android:background
à la couleur blanche comme ça Android:background="@Android:color/white"
Exemple complet ci-dessous:
<Android.support.design.widget.BottomNavigationView
Android:id="@+id/bottom_navigation"
Android:layout_width="match_parent"
Android:layout_height="56dp"
Android:layout_alignParentBottom="true"
Android:background="@Android:color/white"
Android:clickable="true"
app:elevation="8dp"
app:itemIconTint="@drawable/nav_item_color_state"
app:itemTextColor="@drawable/nav_item_color_state"
app:menu="@menu/my_navigation_items" />
Prenez ce FrameLayout
qui dessine l'ombre et ce dégradé xml dessinable :
public class DrawShadowFrameLayout extends FrameLayout {
private Drawable mShadowDrawable;
private final int mShadowElevation = 8;
private int mWidth;
private int mHeight;
private boolean mShadowVisible = true;
public DrawShadowFrameLayout(Context context) {
this(context, null, 0);
}
public DrawShadowFrameLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DrawShadowFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mShadowDrawable = ContextCompat.getDrawable(getContext(), R.drawable.shadow);
if (mShadowDrawable != null) {
mShadowDrawable.setCallback(this);
}
setWillNotDraw(!mShadowVisible);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
updateShadowBounds();
}
private void updateShadowBounds() {
if (mShadowDrawable != null) {
mShadowDrawable.setBounds(0, 0, mWidth, mShadowElevation);
}
ViewCompat.postInvalidateOnAnimation(this);
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (mShadowDrawable != null && mShadowVisible) {
getBackground().setBounds(0, mShadowDrawable.getBounds().bottom, mWidth, mHeight);
mShadowDrawable.draw(canvas);
}
}
public void setShadowVisible(boolean shadowVisible) {
setWillNotDraw(!mShadowVisible);
updateShadowBounds();
}
int getShadowElevation() {
return mShadowVisible ? mShadowElevation : 0;
}
}
Enveloppez votre BottomNavigationView
à l'intérieur de cette disposition comme:
<DrawShadowFrameLayout>
<BottomNavigationView />
</DrawShadowFrameLayout>
Malheureusement, l'ombre native est dessinée sous la vue, nous devons imiter cette ombre ascendante nous-mêmes.
N'oubliez pas d'ajouter également Android:elevation="8dp"
Pour le DrawShadowFrameLayout
.
ne autre approche consiste à étendreBottomNavigationView
et à remplacer draw()
pour faire de même. Cela vous aidera à perdre un FrameLayout
dans votre hiérarchie de vues.
Il s'agit d'un problème dans la bibliothèque de conception et a été signalé ici .
La partie cachée de cette question a déjà été résolue, vous devez donc mettre à jour vos dépendances Gradle vers 25.0.1 pour la bibliothèque Support and Design.
Les ingénieurs de Google insistent sur le fait que le problème de l'effet d'entraînement a également été corrigé, mais je n'ai pas réussi à le faire fonctionner correctement.
Un exemple sur la façon dont le XML du BottomNavigationView
pourrait ressembler peut être vu ici:
<Android.support.design.widget.BottomNavigationView
Android:id="@+id/bottom_navigation"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_alignParentBottom="true"
Android:background="@Android:color/black"
app:itemBackground="@Android:color/white"
app:itemIconTint="@drawable/bottom_navigation_selector"
app:itemTextColor="@drawable/bottom_navigation_selector"
app:menu="@menu/bottom_navigation_menu" />
Mettez le problème en vedette pour le sensibiliser.
J'ai trouvé une solution au problème d'effet d'entraînement.
1) Étant donné que l'application Android: background et : itemBackground ne le font pas travailler correctement supprimer les deux de BottomNavigationView.
2) Créez un nouveau FrameLayout et mettez votre BottomNavigationView à l'intérieur FrameLayout.
3) changez ces propriétés de FrameLayout:
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
4) Enfin, ajoutez la couleur souhaitée pour ButtomNavigationView dans FrameLayout en tant que Android: arrière-plan .
Exemple:
<FrameLayout
Android:id="@+id/buttomnavigation_container"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="@color/blue"><!--Background color for BNV-->
<Android.support.design.widget.BottomNavigationView
Android:id="@+id/nav_view"
Android:layout_width="match_parent"
Android:layout_height="56dp"
app:itemIconTint="@color/bottom_navigation_colors"
app:itemTextColor="@color/bottom_navigation_colors"
app:labelVisibilityMode="labeled"
app:menu="@menu/bottom_nav_menu"/>
</FrameLayout>
bottom_navigation_colors.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item
Android:state_checked="true"
Android:color="#FFFFFF" />
<item
Android:state_checked="false"
Android:color="#C7FFFFFF" />
</selector>
Vous voudrez peut-être ajouter un sélecteur à votre bouton comme:
Android:background="@drawable/my_selector"
/res/drawable/my_selector.xml:
<ripple Android:color="@color/my_favourite_color"
xmlns:Android="http://schemas.Android.com/apk/res/Android" />
En savoir plus: RippleDrawable
Ce que vous pouvez faire, c'est simplement envelopper votre BottomNavigationView
dans AppBarLayout
pour le même effet.
Comme ça
<com.google.Android.material.appbar.AppBarLayout
app:layout_constraintBottom_toBottomOf="parent"
Android:layout_width="match_parent"
Android:background="@Android:color/white"
Android:layout_height="wrap_content">
<com.google.Android.material.bottomnavigation.BottomNavigationView
Android:id="@+id/bottomNav"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"/>
</com.google.Android.material.appbar.AppBarLayout>