【问题标题】:BottomNavigationView - Shadow and Ripple EffectBottomNavigationView - 阴影和波纹效果
【发布时间】:2017-03-12 00:21:44
【问题描述】:

BottomNavigationView 一周前发布时,我真的很高兴,但我遇到了一些让我无法解决的问题,比如在底部导航视图上看到阴影,就像谷歌照片 Android 应用程序向我们展示的那样:

如果我们点击 Google 照片菜单项,我们可以看到像图标和文本颜色一样的蓝色波纹效果(选中时)。

仅实现谷歌提供的解决方案,显示灰色的波纹效果颜色,更糟糕的是,当我们更改底部导航视图的背景颜色时,它不显示(design:itemBackground="...")。

有人知道怎么解决吗?

【问题讨论】:

  • 只需将 BottomNavigationView 的 itemBackground 属性设置为白色对我有用,如下所示:app:itemBackground="@color/colorWhite"

标签: android shadow bottomnavigationview


【解决方案1】:

这是我取得的成就:

我创建了一个demo on GitHub 来帮助你。

首先使用最新的支持库compile "com.android.support:design:$SUPPORT_VERSION"

只有设置白色背景色android:background="@android:color/white"才有效

注意如果您使用app:itemBackground 属性或在您的情况下为design:itemBackground="...",则涟漪效应将消失,因此只需将其删除。

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

处理启用/禁用状态:

您需要创建选择器文件:

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

如果你想在 AppTheme 中更改标准的灰色波纹效果更改 colorControlHighlight 属性,如下所示:

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

对彩色波纹使用 26% 的 alpha。

<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryRipple">#423F51B5</color>

【讨论】:

  • 确实只有在背景为白色时才会出现阴影。那是愚蠢的。知道为什么吗?
  • 我同意这很沮丧,不知道为什么。
  • 嗨@luksha 我完全按照你说的做,但我仍然没有工作:(令人惊讶的是,如果我将 BottomNavigationBar 放在屏幕顶部,它会提升导航视图的底部边框。但是,当我把它放在屏幕底部,海拔停止工作
  • 你是我的救星!谢谢你。无法弄清楚那个影子去了哪里以及为什么。
【解决方案2】:
  1. 要在您的 BottomNavigationView app:elevation="8dp" 中使用阴影高度。
  2. 对于涟漪效果,您只需删除app:itemBackground 并将android:background 设置为类似android:background="@android:color/white" 的白色

下面的完整示例:

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

【讨论】:

    【解决方案3】:

    这是设计库中的一个问题,已报告here

    这个问题的阴影部分已经解决了,所以你应该将你的 Gradle 依赖更新到 25.0.1 以获取支持和设计库。

    Google 工程师坚持认为涟漪效应问题也已修复,但我无法让它正常工作。

    可以在此处查看有关BottomNavigationView 的 XML 外观的示例:

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

    为问题加注星标以增加对它的认识。

    【讨论】:

      【解决方案4】:

      在最新的Material design library中,改变BottomNavigationView中item点击的波纹颜色超级简单。只需在您的 BottomNavigationView 中添加 app:itemRippleColor="@color/your_color"。这是完整的代码

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

      【讨论】:

        【解决方案5】:

        您可能希望在按钮中添加一个选择器,例如:

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

        阅读更多:RippleDrawable

        【讨论】:

          【解决方案6】:

          拿这个画阴影的FrameLayoutthis 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;
              }
          
          }
          

          将您的 BottomNavigationView 包装在此布局中,如下所示:

          <DrawShadowFrameLayout>
            <BottomNavigationView />
          </DrawShadowFrameLayout>
          

          不幸的是,原生阴影是在视图下绘制的,我们必须自己模仿这个向上的阴影。

          不要忘记为DrawShadowFrameLayout 添加android:elevation="8dp"

          Another approach is extending BottomNavigationView 并覆盖 draw() 来做同样的事情。这将帮助您在视图层次结构中释放一个FrameLayout

          【讨论】:

            【解决方案7】:

            我找到了解决涟漪效应问题的方法。

            1) 由于 android:backgroundapp:itemBackground 无法正常工作,请将它们从 BottomNavigationView 中删除。

            2) 创建一个新的 FrameLayout 并将您的 BottomNavigationView 放入 FrameLayout

            3) 更改 FrameLayout 的这些属性:

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

            4)最后将ButtonNavigationView所需的颜色添加到FrameLayout中作为android:background

            例子:

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

            【讨论】:

              【解决方案8】:

              您可以做的只是将您的BottomNavigationView 包裹在AppBarLayout 中以获得相同的效果。

              这样

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

              【讨论】:

                【解决方案9】:

                如何给BottomNavigationView添加波纹效果?

                1. 如果您没有为 BottomNavigationView 属性 app:itemBackground 设置自定义可绘制对象,则仅在下方添加会添加涟漪效果。

                  android:background="@android:color/white"
                  
                2. 如果您已经在使用自定义可绘制选择器

                  app:itemBackground="@drawable/tab_selector"
                  

                然后将波纹标签添加到自定义可绘制对象。

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

                【讨论】:

                • 此解决方案不会产生涟漪效果,只是在单击菜单项时将整个“正方形”的颜色设置为@color/red
                【解决方案10】:

                只需将此属性添加到: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>
                

                【讨论】:

                • 请添加一些链接以展示代码是否有效。
                猜你喜欢
                • 1970-01-01
                • 2018-12-01
                • 1970-01-01
                • 2017-11-15
                • 1970-01-01
                • 2015-02-17
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多