24

I was really happy when BottomNavigationView was released one week ago but I am facing some problems which makes me unable to solve it, like to see a shadow over the BottomNavigationView, on the same way as Google Photos Android App shows us:

The shadow over Bottom Navigation Bar

If we tap on an Google Photos menu item, we can see a ripple effect which is tinted blue like the icon and text color (when selected).

Implementing the solution provided by Google only is displayed a gray ripple effect color, and worse, it is not displayed when we change the background color of the bottomnavigationview (design:itemBackground="...").

Someone knows how to solve it?

Filipe Brito
  • 5,329
  • 5
  • 32
  • 42
  • 1
    Just setting itemBackground attribute of BottomNavigationView to white color worked for me like below: app:itemBackground="@color/colorWhite" – Subhan Ali Jan 27 '20 at 08:49

10 Answers10

58

Here is what I've achieved:

Ripple effect + Elevation gif

I've created a demo on GitHub to help you.

First of all use latest support library compile "com.android.support:design:$SUPPORT_VERSION"

It only works if you set white background color android:background="@android:color/white"

Note that ripple effect will disappear if you use app:itemBackground property or in your case it's design:itemBackground="...", so just remove it.

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

Handling enabled/disabled state:

You need to create selector file:

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

If you want to change standard grey ripple effect change colorControlHighlight proproperty in AppTheme so it looks like following:

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

Use 26% alpha for colored ripples.

<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryRipple">#423F51B5</color>
smac89
  • 39,374
  • 15
  • 132
  • 179
luksha
  • 581
  • 3
  • 10
  • 4
    It's true that shadow appears only when background is white. That's stupid. Any idea why? – WindRider Feb 12 '17 at 11:40
  • I agree it's very frustrated and don't have a clue why. – luksha Feb 13 '17 at 19:18
  • Hi @luksha I do exactly what you say, but I keeps not working yet :( surprisingly, if I place the BottomNavigationBar on top of the screen, It elevate bottom border of navigation view. However, when I place it on bottom of the screen, elevation stops working – inverted_index Jun 19 '17 at 22:25
  • You're my saver! Thank you. Couldn't figure out where was that shadow gone and why. – Oksana Kryvenko Jul 08 '21 at 19:28
23
  1. For Shadow use elevation in your BottomNavigationView app:elevation="8dp".
  2. And for Ripples Effect you just need to remove app:itemBackground and set android:background to white color like that android:background="@android:color/white"

Full example below:

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

In the latest Material design library, it is super easy to change ripple color of item click in BottomNavigationView. Just add app:itemRippleColor="@color/your_color" in your BottomNavigationView. Here is the full code

Add the dependency in build.gradle

build.gradle

implementation "com.google.android.material:material:$materialDesignVersion"

activity_main.xml

<com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/_5sdp"
        android:background="@drawable/bottom_navigation_background"
        app:itemRippleColor="@color/red"
        app:labelVisibilityMode="labeled"
        app:itemIconTint="@color/bottom_navigation_menu_item_tint"
        app:itemTextColor="@color/bottom_navigation_menu_item_tint"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:menu="@menu/home_bottom_navigation_menu" />
Aminul Haque Aome
  • 2,261
  • 21
  • 34
3

This is an issue in the Design library and has been reported here.

The shadow part of this question has already been resolved, so you should update your Gradle dependencies to 25.0.1 for the Support and Design library.

The Google engineers insists that the ripple effect issue has also been fixed, but I haven't been able to get this to work properly.

An example on how the XML for the BottomNavigationView could look like can be seen here:

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

Star the issue to add awareness to it.

Darwind
  • 7,284
  • 3
  • 49
  • 48
2

just add this attribute to: app:itemRippleColor="@color/orange"

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

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:layout_gravity="bottom"
        android:id="@+id/bottomNavigation"
        android:background="@color/dark"
        app:itemRippleColor="@color/orange"
        android:layout_width="match_parent"
        app:menu="@menu/bottom_nav_menu"
        app:itemIconTint="@color/bottom_nav_color"
        app:itemTextColor="@color/bottom_nav_color"
        android:layout_height="wrap_content"/>

</FrameLayout>
Khanh Le
  • 21
  • 1
1

You might want to add a selector to your button like:

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

Read more: RippleDrawable

Kamran Ahmed
  • 7,661
  • 4
  • 30
  • 55
1

Take this FrameLayout that draws shadow and this gradient drawable xml:

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

}

Wrap your BottomNavigationView inside this this layout like:

<DrawShadowFrameLayout>
  <BottomNavigationView />
</DrawShadowFrameLayout>

Unfortunately, the native shadow is drawn under the view, we have to mimic this upward shadow ourselves.

Dont forget to add android:elevation="8dp" for the DrawShadowFrameLayout too.

Another approach is extending BottomNavigationView and overriding draw() to do the same. This will help you loose one FrameLayout in your view hierarchy.

enter image description here Zoomed

usernotnull
  • 3,480
  • 4
  • 25
  • 40
Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148
1

I've found a solution for ripple effect problem.

1) Since the android:background and app:itemBackground don't work correctly delete both of them from BottomNavigationView.

2) Create a new FrameLayout and put your BottomNavigationView inside FrameLayout.

3) change these properties of the FrameLayout:

android:layout_width="match_parent"
android:layout_height="wrap_content"

4)Finally Add your desired color for ButtomNavigationView into FrameLayout as android:background.

Example:

<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

Kh.Nomani
  • 185
  • 2
  • 12
0

What you can do is just wrap your BottomNavigationView in AppBarLayout for the same effect.

Like this

<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>
OhhhThatVarun
  • 3,981
  • 2
  • 26
  • 49
-1

How to add the ripple effect to the BottomNavigationView?

  1. If you are not setting a custom drawable for BottomNavigationView property app:itemBackground then only adding below will add a ripple effect.

    android:background="@android:color/white"
    
  2. If you are already using a custom drawable selector

    app:itemBackground="@drawable/tab_selector"
    

then add a ripple tag to the custom drawable.

    <?xml version="1.0" encoding="utf-8"?>
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@android:color/white">
        <item>
            <selector >
                <item
                    android:drawable="@color/red"
                    android:state_checked="true" />
                <item
                    android:drawable="@android:color/white"
                    android:state_checked="false" />
            </selector>

        </item>
Muhammad Maqsood
  • 1,622
  • 19
  • 25
  • This solution doesn't create a ripple effect but just sets the color of the whole "square" to @color/red when the menu item is clicked – Gianluca Veschi Feb 16 '22 at 11:03