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