【问题标题】:Android Ripple drawable and state focused (DPAD navigation)Android Ripple 可绘制和以状态为中心(DPAD 导航)
【发布时间】:2025-12-08 05:25:01
【问题描述】:

我正在尝试为 Android TV 和 Amazon FireTV 应用程序中的按钮实现涟漪效果背景(通过 DPAD 导航)。我正在使用 AppCompat,但由于默认按钮样式都使用波纹,我现在使用自定义可绘制背景,没有任何波纹,只是一个普通的选择器。

我试图实现的行为

  • 默认(无焦点):灰色按钮
  • 聚焦:黄色按钮
  • 按下:黄色,顶部有深黄色波纹

实际发生的情况

  • 默认(无焦点):灰色按钮 => 确定
  • 聚焦:黄色,顶部有部分透明的深黄色 => 问题。
  • 按下:深黄色波纹 => 确定

这种颜色混合似乎是波纹可绘制对象的默认行为,这使得它们实际上无法用于电视应用程序。

我有机会逃脱吗?我想要的基本上是一个不会修改背景颜色并且只在顶部绘制的波纹。

【问题讨论】:

  • 我也遇到了同样的问题,你找到解决办法了吗?,我的重点部分也没有使用 D-Pad。
  • 这里有同样的问题。有什么解决办法吗?
  • 你找到解决办法了吗?

标签: android android-xml android-appcompat android-tv rippledrawable


【解决方案1】:

根据https://*.com/a/29777616/332798,如果您为波纹添加一个遮罩,这将使默认状态透明并且不会再影响焦点颜色。

【讨论】:

    【解决方案2】:

    我知道这个问题已经很老了,但我找到了一个适合我的解决方案:

    <?xml version="1.0" encoding="utf-8"?>
    <ripple
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/ripple">
        <item android:id="@android:id/mask">
            <selector>
                <!-- for hard key, ripple should be visible -->
                <item android:state_pressed="true">
                    <shape android:shape="rectangle">
                        <solid android:color="@android:color/black"/>
                        <corners android:radius="@dimen/cornerRadius"/>
                    </shape>
                </item>
                <!-- on focused state, set the color to transparent, no ripple will be visible -->
                <item
                    android:state_focused="true">
                    <color android:color="@android:color/transparent"/>
                </item>
                <!-- default behavior, ripple should be visible-->
                <item>
                    <shape android:shape="rectangle">
                        <solid android:color="@android:color/black"/>
                        <corners android:radius="@dimen/cornerRadius"/>
                    </shape>
                </item>
            </selector>
        </item>
        <!-- background color-->
        <item >
            <color android:color="@android:color/background"/>
        </item>
    </ripple>
    

    此行为的问题在于掩码项。 RippleDrawable 的文档说:

    如果设置了遮罩层,波纹效果将在该层被绘制到其余子层的合成上之前被遮罩。

    如果未设置遮罩层,则波纹效果将针对子层的合成进行遮罩。

    据我了解,如果您使用 DPAD/HardKeys,那么掩码项目将获得焦点。为了排除遮罩项,我添加了一个选择器并用透明颜色覆盖了聚焦状态的行为。因此,如果视图聚焦,则遮罩将不可见。作为默认行为,必须为蒙版设置纯色,否则波纹将不可见。在我的例子中,我添加了一个形状,因为我希望我的波纹有圆角。

    另外我为选择器添加了按下状态,因为我还想对硬键输入产生连锁反应。

    最后,我添加了一个带有背景颜色的附加项目。

    【讨论】: