BottomNavigationView - Shadow and Ripple Effect

后端 未结 8 679
闹比i
闹比i 2020-12-14 08:41

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

相关标签:
8条回答
  • 2020-12-14 09:00

    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.

    0 讨论(0)
  • 2020-12-14 09:08

    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>
    

    0 讨论(0)
  • 2020-12-14 09:10

    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.

    0 讨论(0)
  • 2020-12-14 09:14

    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

    0 讨论(0)
  • 2020-12-14 09:14

    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>
    
    0 讨论(0)
  • 2020-12-14 09:15

    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" />
    
    0 讨论(0)
提交回复
热议问题