web-dev-qa-db-fra.com

BottomNavigationView - Effet d'ombre et d'ondulation

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:

The shadow over Bottom Navigation Bar

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?

14
Filipe Brito

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>
39
luksha
  1. Pour l'ombre, utilisez l'élévation dans votre BottomNavigationView app:elevation="8dp".
  2. Et pour Ripples Effect, il vous suffit de supprimer 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" />
15
Étienne Théodore

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.

enter image description hereZoomed

1

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.

1
Darwind

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>

Image

0
Kh.Nomani

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

0
Kamran Ahmed

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>
0
Varun Raj