如何在具有按钮背景颜色的按钮上添加涟漪效果?

167

我创建了一个按钮,并想为该按钮添加水波纹效果!

我创建了一个按钮背景XML文件:(bg_btn.xml)

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:startColor="#FFFFFF" android:endColor="#00FF00" android:angle="270" />
<corners android:radius="3dp" />
<stroke android:width="5px" android:color="#000000" />
</shape>

这是我的涟漪效果文件:(ripple_bg.xml)

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

这是我想要添加涟漪效果的按钮:

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:layout_centerHorizontal="true"
android:layout_marginTop="173dp"
android:textColor="#fff"
android:background="@drawable/ripple_bg"
android:clickable="true" />

但是在添加涟漪效果后,按钮的背景变成透明的,并且只有在点击时才显示按钮,就像这样:

点击之前

点击之后

但我需要按钮的背景颜色和涟漪效果,我在 Stack Overflow 的不同博客中找到了一些代码,但仍然无法正常工作!


请下次在上传之前调整大小,使截图更小。 - user25
@user25,你也可以在图片链接后面添加“l”或“m”。(请参见我的编辑) - Suragch
那些想要依赖于 foreground 属性的人,可以使用这个向后兼容的 hack - https://dev59.com/CVkS5IYBdhLWcg3wV1Zy#65213848 - Anoop M Maddasseri
13个回答

247

这是另一个可绘制的XML,适用于那些希望将所有渐变背景、圆角半径和涟漪效果添加在一起的人:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorPrimaryDark">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorPrimaryLight"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>
</ripple>

将这段代码添加到您按钮的背景中。

<Button
    ...
    android:background="@drawable/button_background" />

注:此答案适用于 Android API 21 及以上版本。


12
@pei 你们是怎么获取这些信息的? 我的意思是,你们怎么知道有一个叫做ripple的XML元素可以完成这项工作? - user5587563
2
这是Material Design中使用的概念之一。请在Android Studio的drawable xml中开始键入新的根标签,然后您应该能够看到所有可用的标签,包括“ripple”。 - Pei
1
口罩条目的用途是什么? - Prashant
13
需要 API 级别为 21。 - M.kazem Akhgary
2
它有效,但工作原理并未解释。它应该与项目ID相关联。应该被引用。 - oiyio
显示剩余5条评论

211
如果视图已经有背景,并且具有 "android:clickable =“true”" 属性,请将 "?attr/selectableItemBackground" 添加到视图的 "android:foreground" 属性中。

并不总是有效,但是您可以按照已接受答案的评论中所述,为涟漪效果添加背景。 - Tyler
我不得不使用这个解决方案,因为我已经为我的按钮使用了自定义背景。它非常有效。 - bnayagrawal
@ROAR,没错,但至少:“这不是一个错误;应用程序将简单地忽略该属性。然而,如果该属性对您的应用程序的外观或功能很重要,您应该考虑找到一种替代方法来实现相同的结果,只使用可用的属性,然后您可以选择在layout-vNN文件夹中创建布局的副本,在API NN或更高版本上使用它,以便利用更新的属性。”因此,它在API 23以上的设备上运行良好,在API 23以下的设备上被忽略(我们可以使用tools:ignore="UnusedAttribute")。 - JorgeAmVF
没有 Android 支持库,它将是 ?android:attr/selectableItemBackground(使用 android:attr 而不是 attr)。 - Weekend
9
API版本低于23时,android:foreground属性无效。 - Vadim Kotov
1
@VadimKotov 谷歌应该完全禁止所有小于23的API级别。我完全找不到任何借口让公司仍然要求为这些史前版本开发。 - RFM

81

为 Android 按钮添加水波纹效果/动画

只需将您的按钮背景属性替换为android:background="?attr/selectableItemBackground",您的代码就像这样。

      <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/selectableItemBackground"
        android:text="New Button" />

另一种为安卓按钮添加水波纹效果/动画的方法

使用这种方法,您可以自定义水波纹效果的颜色。首先,您必须在可绘制资源目录中创建一个xml文件。创建ripple_effect.xml文件并添加以下代码。 res/drawable/ripple_effect.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

将按钮的背景设置为上述可绘制资源文件

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_effect"
    android:padding="16dp"
    android:text="New Button" />

1
对我来说,涟漪效果并没有出现。它只是按钮的颜色切换 :/ 我的 Android 版本是 5.1.1,所以应该可以工作。你能帮忙吗?我按照你的步骤走了。 - ugola
android:color应该与主要的android:color不同,否则您将无法看到涟漪效果。 - SpyZip
3
如果你想要一个背景,只需将另一个元素添加到波纹中,例如:<item android:drawable="?attr/colorPrimary"/>。 - Tyler

45

除了 Jigar Patel 的解决方法之外,将下面的内容添加到 ripple.xml 中可以避免按钮背景透明。

<item
    android:id="@android:id/background"
    android:drawable="@color/your-color" />

完整的XML:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/your-color"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/your-color" />
        </shape>
    </item>
    <item
        android:id="@android:id/background"
        android:drawable="@color/your-color" />
</ripple>

使用此 ripple.xml 作为您的按钮背景:

android:background="@drawable/ripple"

3
除非你想要一个椭圆形的遮罩,否则我们不需要使用 <item android:id="@android:id/mask"> [...]。谢谢你的回答! - Filipe Brito
这个 <item android:id="@android:id/mask"> 到底是做什么的?我创建了两个类似的元素,一个带有该属性,一个没有,它们看起来完全一样。 - Sartheris Stormhammer
来自官方文档的@SartherisStormhammer:如果设置了蒙版层,则涟漪效果将在绘制剩余子层的组合之前被该层蒙版。如果没有设置蒙版层,则涟漪效果将在子层的组合上被蒙版。这是链接,https://developer.android.com/reference/android/graphics/drawable/RippleDrawable.html - Sudheesh R
@SudheeshR 这只会让事情更加混乱。 - Sartheris Stormhammer
从官方文档来看,我认为这很清楚。涟漪效果将绘制在子层/遮罩图层上方。请再次阅读文档,你会明白的。@SartherisStormhammer - Sudheesh R
显示剩余2条评论

40

当按钮有来自Drawable的背景时,我们可以将涟漪效果添加到前景参数中。请查看以下代码,它适用于我的具有不同背景的按钮。

    <Button
    android:layout_width="wrap_content"
    android:layout_height="40dp"
    android:gravity="center"
    android:layout_centerHorizontal="true"                                                             
    android:background="@drawable/shape_login_button"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:text="@string/action_button_login"
     />
添加以下参数以实现涟漪效果。
   android:foreground="?attr/selectableItemBackgroundBorderless"
   android:clickable="true"

请参考以下链接: https://jascode.wordpress.com/2017/11/11/how-to-add-ripple-effect-to-an-android-app/


3
android:foreground 属性在低于 API 23 的版本中没有任何效果。 - Ali Khaki
1
这种方法的一个缺点是,即使我的按钮背景是椭圆形,涟漪也会传播到矩形边缘。 - iCantC

26

AppCompat v7+

如果您不使用?android:前缀,您的应用程序将崩溃。

根据您的偏好,您应该使用"?android:attr/selectableItemBackground""?android:attr/selectableItemBackgroundBorderless"。我更喜欢Borderless

您可以将其放置在android:backgroundandroid:foreground中以保留现有属性。

元素必须具有android:clickable="true"android:focusable="true",才能使此功能正常工作,但许多元素(如按钮)默认情况下将它们设置为true

<Button
    ...
    android:background="@color/white"
    android:foreground="?android:attr/selectableItemBackgroundBorderless"
/>
<TextView
    ...
    android:background="?android:attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:focusable="true"
/>

编程方式(Java)

TypedValue value = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
myView.setBackgroundResource(value.resourceId);
myView.setFocusable(true); // If needed for view type

以编程方式(Kotlin)

val value = TypedValue()
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
myView.setBackgroundResource(value.resourceId)
myView.setFocusable(true) // If needed for view type

Kotlin可重复使用的扩展函数

myView.ripple()

fun View.ripple(): View {
    val value = TypedValue()
    context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
    setBackgroundResource(value.resourceId)
    isFocusable = true // Required for some view types
    return this
}

如果你添加了 ?android,你将不会使用 AppCompat 库,而是使用操作系统中的库(因此在 api<11 中会崩溃)。你必须在没有 android: 命名空间前缀的情况下使用它。 - David Miguel
感谢留言。我预计大多数开发人员的最小级别都在11级以上,所以没有问题。 - Gibolt

8

添加前景和可点击属性对我有用。

<Button
    ... 
    android:background="@color/your_color"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true" />

1
Api 级别 23 及以上 - Kumar Santanu

8

一个简单的方法是按照这里所概述的将视图主题设置为特定值。

some_view.xml

<ImageView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:background="?attr/selectableItemBackgroundBorderless"
   android:focusable="true"
   android:src="@drawable/up_arrow"
   android:theme="@style/SomeButtonTheme"/>

some_style.xml

<style name="SomeButtonTheme" >
   <item name="colorControlHighlight">@color/someColor</item>
</style>

7

除了Sudheesh R之外

为具有带圆角的按钮矩形形状的Android按钮添加涟漪效果/动画

创建xml文件res/drawable/your_file_name.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/colorWhite"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="50dp" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorAccent"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="50dp" />
        </shape>
    </item>
</ripple>

5

试试这个:

<Button
    android:background="@drawable/btn_corner"
    android:clickable="true"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:gravity="center_vertical|center_horizontal"
    android:id="@+id/btn_location"
    android:layout_gravity="center"
    android:layout_height="38dp"
    android:layout_marginBottom="24dp"
    android:layout_marginTop="24dp"
    android:layout_width="121dp"
    android:paddingLeft="13dp"
    android:paddingRight="13dp"
    android:text="Save"
    android:textColor="@color/color_white" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接