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:
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?
Here is what I've achieved:
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>
- For Shadow use elevation in your BottomNavigationView
app:elevation="8dp"
. - And for Ripples Effect you just need to remove
app:itemBackground
and setandroid:background
to white color like thatandroid: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" />
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.
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.
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
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>
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>
来源:https://stackoverflow.com/questions/40316411/bottomnavigationview-shadow-and-ripple-effect