BottomNavigationView - 阴影和波纹效果

Posted

技术标签:

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

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

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

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

有人知道怎么解决吗?

【问题讨论】:

只需将 BottomNavigationView 的 itemBackground 属性设置为白色对我有用,如下所示:app:itemBackground="@color/colorWhite" 【参考方案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_
    android:layout_
    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】:
    要在您的 BottomNavigationView app:elevation="8dp" 中使用阴影高度。 对于涟漪效果,您只需删除app:itemBackground 并将android:background 设置为类似android:background="@android:color/white" 的白色

下面的完整示例:

<android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_
        android:layout_
        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_
    android:layout_
    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_
        android:layout_
        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】:

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


将您的 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_
android:layout_

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

例子:

<FrameLayout
 android:id="@+id/buttomnavigation_container"
 android:layout_
 android:layout_
 android:background="@color/blue"><!--Background color for BNV-->
 <android.support.design.widget.BottomNavigationView
    android:id="@+id/nav_view"
    android:layout_
    android:layout_
    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_
            android:background="@android:color/white"
            android:layout_>

        <com.google.android.material.bottomnavigation.BottomNavigationView
                android:id="@+id/bottomNav"
                android:layout_
                android:layout_/>

</com.google.android.material.appbar.AppBarLayout>

【讨论】:

【参考方案9】:

如何给BottomNavigationView添加波纹效果?

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

    android:background="@android:color/white"
    

    如果您已经在使用自定义可绘制选择器

    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_
    android:layout_>

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

</FrameLayout>

【讨论】:

请添加一些链接以展示代码是否有效。

以上是关于BottomNavigationView - 阴影和波纹效果的主要内容,如果未能解决你的问题,请参考以下文章

BottomNavigationView - 如何获取选定的菜单项?

BottomNavigationView 的标题颜色为渐变

安卓。具有单一活动方法的 BottomNavigationView

如何使用 material.BottomNavigationView 设置 Jetpack 导航

BottomNavigationView 的使用

Android关于BottomNavigationView效果实现指南