Android,设置按钮的背景颜色会失去涟漪效果
Posted
技术标签:
【中文标题】Android,设置按钮的背景颜色会失去涟漪效果【英文标题】:Android, setting background color of button loses ripple effect 【发布时间】:2016-11-14 14:17:47 【问题描述】:在为 android 按钮添加颜色后,它会失去涟漪效果,让用户感觉就像是响应式点击。我该如何解决?我已经搜索了许多解决方案,但我找不到一个明确的不模棱两可的解决方案。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
tools:context=".ClockInOutFragment">
<AnalogClock
android:id="@+id/clock"
android:layout_
android:layout_
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/date_and_time"/>
<RelativeLayout
android:id="@+id/date_and_time"
android:layout_
android:layout_
android:layout_margin="10dp">
<TextView
android:id="@+id/time_digits"
android:layout_
android:layout_
android:text="12:10"
android:textSize="45sp"/>
<TextView
android:id="@+id/am_pm"
android:layout_
android:layout_
android:layout_alignBaseline="@+id/time_digits"
android:layout_toRightOf="@+id/time_digits"
android:paddingLeft="3dp"
android:text="PM"
android:textSize="20sp"/>
<TextView
android:id="@+id/date"
android:layout_
android:layout_
android:layout_below="@+id/time_digits"
android:text="Mon, July 11"
android:textSize="22sp"/>
</RelativeLayout>
<!--Clock in and out buttons-->
<LinearLayout
android:layout_
android:layout_
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:orientation="horizontal">
<Button
android:id="@+id/textView3"
android:layout_
android:layout_
android:layout_weight="1"
android:background="#4CAF50"
android:gravity="center"
android:text="Clock In"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#FFFFFF"/>
<!--Divider between the clock in and out button-->
<View
android:layout_
android:layout_
android:background="#B6B6B6"/>
<Button
android:id="@+id/textView4"
android:layout_
android:layout_
android:layout_weight="1"
android:background="#FF5252"
android:gravity="center"
android:text="Clock Out"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#FFFFFF"/>
</LinearLayout>
</RelativeLayout>
【问题讨论】:
【参考方案1】:您可以使用附加的波纹可绘制来添加波纹效果和背景颜色:
你的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_
android:layout_>
<Button
android:id="@+id/button_connect"
android:layout_
android:layout_
android:layout_marginTop="20dip"
android:fontFamily="sans-serif"
android:text="Connect"
android:background="@drawable/ripple"
android:textColor="#FFFFFF"
android:textSize="18sp" />
</LinearLayout>
ripple.xml(除了波纹效果之外,您还可以在此处添加背景颜色):
<?xml version="1.0" encoding="utf-8"?>
<!-- in drawable folder-->
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="?android:colorAccent" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<!-- put your background color here-->
<solid android:color="@color/default_color" />
</shape>
</item>
</ripple>
【讨论】:
android如何区分哪一种是蒙版,哪一种是默认颜色? 按 ID。例如 - android:id="@android:id/mask" 这适用于更改菜单背景并保留涟漪效果【参考方案2】:执行此操作的一种非常简单直接的方法是将按钮的?attr/selectableItemBackground
设置为android:foreground
属性。以下 xml 完全有效且有效
<Button
android:id="@+id/btn"
android:layout_
android:layout_
android:background="@android:color/white"
android:foreground="?attr/selectableItemBackground"/>
【讨论】:
不错。但是,23 版不支持向后兼容。 如何改变效果的颜色? 这不适用于使用 style="@style/Widget.AppCompat.Button.Colored" 的弯曲按钮 结果是阴影有尖角,而不是弯曲的角。 适用于Widget.AppCompat.Button.Borderless
【参考方案3】:
不要改变 Button 的背景。换个主题。
<style name="ButtonGray">
<item name="colorButtonNormal">@color/gray</item>
</style>
在你的xml文件中
<Button
android:id="@+id/accept_button"
android:layout_
android:layout_
android:layout_weight="1"
android:text="@string/button_accept_group"
android:theme="@style/ButtonGray"/>
或者您可以将其添加到您的主应用主题中
<style name="AppTheme"
parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorButtonNormal">@color/primary_color</item>
</style>
并且不需要更改按钮背景。
如果你想要完全自定义的背景,你需要创建你的选择器。你可以在那里设置涟漪效应。
【讨论】:
【参考方案4】:只需使用:
android:backgroundTint="#4CAF50"
代替:
android:background="#4CAF50"
别忘了把你的Button
改成android.support.v7.widget.AppCompatButton
【讨论】:
这不适用于androidx.appcompat.widget.AppCompatButton
【参考方案5】:
MaterialButton没有答案,所以我把它放在这里。
对于 MaterialButton (com.google.android.material.button.MaterialButton),使用“backgroundTint”和“rippleColor”。
<com.google.android.material.button.MaterialButton
android:id="@+id/button_sign_in"
android:layout_
android:layout_
app:backgroundTint="@android:color/white"
app:rippleColor="?attr/colorControlHighlight"
?attr/colorControlHighlight
是默认的波纹颜色,你可以改变这个值。
【讨论】:
【参考方案6】:实际上,您可以使用drawables的<layer-list>
将涟漪效果与任何其他drawable结合起来。这也是 pre-lolipop 的通用解决方案:我已经在许多配置中对其进行了测试。
唯一的问题是当?selectableItemBackground
出现在<layer-list>
中时pre-lolipop 会崩溃,所以我们必须以编程方式创建LayerDrawable。
一个非常快速的简单解决方案如下所示:
为您的视图指定
android:background="?selectableItemBackground"
然后在代码中的任何地方创建 mySpecialDrawable 并执行此操作:
Drawable[] layers = mySpecialDrawable, getBackground();
setBackgroundDrawable(new LayerDrawable(layers).mutate());
请注意,LayeredDrawable 的 .mutate()
在这里是必不可少的!
当您已经拥有自定义 View 并且更喜欢扩展其功能和兼容性而不是添加额外的空 FrameLayout 作为父级时,更复杂的解决方案可能会很有用。
在attrs.xml里面放:
<resources>
<declare-styleable name="MyView">
<attr name="selectableBackground" format="reference"/>
<attr name="backgroundDrawable" format="reference"/>
</declare-styleable>
</resources>
然后在你的 View-descendant 类中:
private Drawable selectableBackground;
private Drawable backgroundDrawable;
public MyView(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
try
TypedArray attributeArray;
attributeArray = context.obtainStyledAttributes(attrs, R.styleable.MyView);
int id = attributeArray.getResourceId(R.styleable.MyView_selectableBackground, -1);
if (id != -1)
selectableBackground = ResourcesCompat.getDrawable(getResources(), id, context.getTheme());
id = attributeArray.getResourceId(R.styleable.MyView_backgroundDrawable, -1);
if (id != -1)
backgroundDrawable = ResourcesCompat.getDrawable(getResources(), id, context.getTheme());
constructBackground();
attributeArray.recycle();
catch (Exception e)
Log.e(this.toString(), "Attributes initialization error", e);
throw e;
void setSelectableBackground(Drawable drawable)
selectableBackground = drawable;
constructBackground();
void setDrawable(Drawable drawable)
backgroundDrawable = drawable;
constructBackground();
private void constructBackground()
if (selectableBackground != null)
if (backgroundDrawable != null)
Drawable[] layers = backgroundDrawable, selectableBackground;
setBackgroundDrawable(new LayerDrawable(layers).mutate()); // Both, using layers
else setBackgroundDrawable(selectableBackground); // Selectable only
else setBackgroundDrawable(backgroundDrawable); // Background only or null
我更喜欢这种方法,因为它没有像 android:foreground
属性这样的问题,它是 23+ 或在 FrameLayout 中包含可点击视图的额外开销。
【讨论】:
【参考方案7】:你应该使用样式
<style parent="Theme.AppCompat.Light" name="RaisedButtonGreen">
<item name="colorButtonNormal">@color/green</item>
<item name="colorControlHighlight">@color/greenLight</item>
<item name="android:textColor">@android:color/white</item>
</style>
这是最优解
<Button
android:layout_
android:layout_
android:text="Button with ripple for style"
android:theme="@style/RaisedButtonGreen"/>
【讨论】:
以上是关于Android,设置按钮的背景颜色会失去涟漪效果的主要内容,如果未能解决你的问题,请参考以下文章
如何在保留其他样式属性的同时更改 Android Button 波纹颜色?