当使用?attr/selectableItemBackground作为背景时,我该如何修改涟漪颜色?

131

我看到一些Stack Overflow的问题,它们给出了一些可能实现我想要的方法。例如:

  1. 在styles.xml中使用colorControlHighlight属性。

    这是我的styles-v21.xml:

<style name="SelectableItemBackground">
    <item name="android:colorControlHighlight">#5677FC</item>
    <item name="android:background">?attr/selectableItemBackground</item>
</style>

我的小部件:

<TextView
    android:id="@+id/tv_take_photo_as_bt"
    android:layout_width="280dp"
    android:layout_height="48dp"
    android:text="@string/act_take_photo"
    style="@style/SelectableItemBackground"/>

但是它不起作用。我还尝试将parent="Theme.AppCompat"添加到"SelectableItemBackground"样式中,或更改为colorControlHighlight(无android:前缀),或更改为?android:attr/selectableItemBackground,但都没有用。

  • 在布局中使用backgroundTint属性。

    因此,我向我的TextView中添加了android:backgroundTint="#5677FC"。仍然没有用。然后我尝试将android:backgroundTintMode更改为src_insrc_atop,但它们从未有过区别。

  • 那么,当我将?attr/selectableItemBackground用作背景时,如何更改涟漪颜色。 我只关注Lollipop及以上版本。 预先感谢您!

    10个回答

    181

    最后我找到了解决方案:不要直接在主题SelectableItemBackground中使用android:colorControlHighlight,而是应该编写另一个样式:

    最后我找到了解决方案:不要直接在主题SelectableItemBackground中使用android:colorControlHighlight,而是应该编写另一个样式:

    <style name="SelectableItemTheme">
        <item name="colorControlHighlight">@color/ripple_color</item>
    </style>
    

    那么:

    <style name="SelectableItemBackground">
        <item name="android:theme">@style/SelectableItemTheme</item>
        <item name="android:background">?attr/selectableItemBackground</item>
    </style>
    

    最后在 layout.xml 中的 View 添加 style="@style/SelectableItemBackground"

    2016/8/26 更新 在 N 版本发布后,我发现有时候我们不能使用这种方法为某些类型的 View(例如 CardView)设置波纹颜色。现在我强烈建议开发者使用 RippleDrawable,它也可以在 xml 中声明。以下是一个例子:

    当用户触摸/点击 API21 以上版本中的 CardView 时,我想显示涟漪效果,在 Lollipop 之前当然还应该有另一种反馈。因此我应该编写:

    <android.support.v7.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:foreground="@drawable/selectable_item_background"/>
    

    并且在drawable文件夹中有selectable_item_background:

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_pressed="false" android:drawable="@android:color/transparent" />
        <item android:drawable="@color/color_clicked" />
    </selector>
    

    drawable-v21文件夹中的selectable_item_background

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/ripple_black" />
    </selector>
    

    最后,在 drawable(或 drawable-v21)文件夹中的 ripple_black

    <ripple
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:color="@color/color_clicked"
        tools:ignore="NewApi" /> <!--you can remove this line if it's in v21 folder-->
    

    就这样了。对于其他视图,也许你应该使用android:background="@drawable/selectable_item_background"。别忘了为它们设置一个OnClickListenerOnTouchListener或类似的东西,否则涟漪效果不会显示。


    14
    对我来说,使用colorControlHighlight而不是android:colorControlHighlight更好,否则只适用于v21+。 - Liuting
    1
    这不是正确的答案,请查看下面 @harrane 的答案。 - Jin
    2
    如果您没有设置ClickListener,请将视图设置为可点击 clickable="true",涟漪效果就会起作用。 - hedisam

    68

    涟漪效果对于不同版本的设备

    harrane和Liuting说得对。接受的答案并不是最好的方法。 让我通过代码展示如何在Android 5.0以下以及更高版本中更改涟漪的颜色。

    1. Your AppTheme should inherit from any AppCompat theme and contain colorControlHighlight attribute (without 'android:' prefix)

      <!-- Application theme. -->
      <style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
      <item name="colorControlHighlight">#40ffffff</item>
      </style>
      
    2. Your view should contain clickable="true" (or should have a click listener set programmatically) and background should be "?attr/selectableItemBackgroundBorderless" or "?attr/selectableItemBackground" :

      <LinearLayout
      ...
      android:clickable="true"
      android:background="?attr/selectableItemBackgroundBorderless"/>
      

    注意:如果您的父视图具有白色背景,则看不到涟漪效果,因为它是白色的。更改colorControlHighlight值以使用不同的颜色。

    此外,如果您希望在不同的活动中使用不同的涟漪颜色,则可以在清单文件中为每个活动设置个人主题,例如:

           <activity
            android:name="com.myapp.GalleryActivity"
            android:theme="@style/RedRippleTheme"
            />
    

    同一活动中不同片段可以使用不同的涟漪颜色吗?

    您可以在运行时为每个片段更改Activity主题的属性。只需要在片段使用自定义样式之前覆盖它们,并将其应用于当前主题:

    values/styles.xml 文件中:

        <style name="colorControlHighlight_blue">
           <item name="colorControlHighlight">@color/main_blue_alpha26</item>
        </style>
    

    然后,在您的片段中,在onCreateView()之前进行充气:
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
           getContext().getTheme().applyStyle(R.style.colorControlHighlight_blue, true); //blue ripple color
           View view = inflater.inflate(R.layout.my_fragment_layout, container, false);
           return view;
        }
    

    这种样式仅适用于此片段。


    不同的视图使用不同的涟漪颜色?(Lollipop +)

    您可以使用colorControlHighlight属性为每个视图单独更改涟漪颜色,如果您直接应用它们于视图,则无法正常工作

        <TextView
         ...
         colorControlHighlight="#40ffffff"/> <!-- DOESN'T WORK -->
    

    你应将其应用为主题:

    <TextView
      ...
      android:theme="@style/colorControlHighlight_blue"/>
    

    P.S. 同时,有时候这种方法可以帮助你解决涟漪效果的未知问题。在我的情况下,我使用了第三方滑动库,导致整个布局的涟漪效果混乱,将此主题明确添加到所有可点击的视图中对我很有帮助。


    16

    API版本高于21时,它会显示带有颜色的涟漪效果,并在按下时显示简单的灰色背景。请添加以下样式:

    <style name="AppTheme.MyRipple">
       <item name="colorControlHighlight">@color/your_color</item>
       <item name="android:background">?selectableItemBackgroundBorderless</item>
    </style>
    

    并将其设置为视图:

    <Button
       ...
       android:theme="@style/AppTheme.MyRipple" />
    

    6
    需要注意的是,确实应该使用android:theme而不是人们通常使用的style - android developer

    12

    请按照以下步骤进行:

    1. Make changes to button view in your layout.xml
    2. Add new styles in styles.xml
    

    您的布局文件your_layout.xml

    <Button
                            android:id="@+id/setup_submit_button"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginTop="16dp"
                            android:text="@string/action_sign_in"
                            android:textStyle="bold"
                            android:background="@color/colorPrimary"
                            android:textColor="@color/white"
                            style="@style/SelectableItemBackground"
                            android:foreground="?android:attr/selectableItemBackground"/>
    

    -style属性调用我们创建的样式。

    -Foreground属性调用安卓默认的可选属性。

    styles.xml

     <style name="SelectableItemTheme">
            <item name="colorControlHighlight">@color/white</item>
        </style>
    
    
        <style name="SelectableItemBackground">
            <item name="android:theme">@style/SelectableItemTheme</item>
            <item name="android:background">?attr/selectableItemBackground</item>
        </style>
    

    1
    工作于CardView,谢谢。 - VinceStyling

    7

    0
    在你的xml中设置背景:
    <View
        android:id="@+id/click_view"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_gravity="center"
        android:background="?attr/selectableItemBackgroundBorderless" <!-- Set ripple this way -->
        android:contentDescription="@null" />
    

    在你的代码中改变它的颜色:
    // Take borderless ripple
    val ripple = clickView.background as? RippleDrawable 
    
    // Change color here
    ripple?.setColor(ColorStateList.valueOf(Color.RED))
    

    不知道Lollipop的工作原理。


    0

    这段代码对我来说可以创建涟漪效果:

    public static void setRippleDrawable(View view, int normalColor, int touchColor) {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                RippleDrawable rippleDrawable = new RippleDrawable(ColorStateList.valueOf(touchColor), view.getBackground(), null);
                view.setBackground(rippleDrawable);
            } else {
                StateListDrawable stateListDrawable = new StateListDrawable();
                stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(touchColor));
                stateListDrawable.addState(new int[]{android.R.attr.state_focused}, new ColorDrawable(touchColor));
                stateListDrawable.addState(new int[]{}, new ColorDrawable(normalColor));
                view.setBackground(stateListDrawable);
                }
        } catch (Exception e) {
            Log.e(LOG_TAG, "" + e);
        }
    }
    

    我没有找到任何修改selectableItemBackground属性的方法。这就是为什么我像上面那样做的原因。


    0
    在深黑色主题(或其他主题)的应用程序中,尝试像下面这样使用: 首先在drawable文件夹中创建ripple_effect.xml,并添加以下代码。
    <?xml version="1.0" encoding="utf-8"?>
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="#f5f5f5">
        <item android:id="@android:id/mask">
            <shape android:shape="rectangle">
                <solid android:color="#f5f5f5" />
    
            </shape>
        </item>
    
    </ripple>
    

    然后将背景设置为您的任何视图,如线性布局、按钮、文本视图等。

     <TextView
                        android:id="@+id/tvApply"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:background="@drawable/ripple_effect"
                        android:clickable="true"
                        android:text="APPLY"
                        android:textColor="#FFFFFF"
                        android:gravity="center"
                        android:textSize="@dimen/_8sdp"
                        android:padding="@dimen/_8sdp"
                        android:focusable="true" />
    

    0
    如果你想以编程的方式来实现,我已经研究过的这个解决方案应该至少对大多数情况都有效。
    fun View.setBackgroundTintColor(@ColorInt color: Int) {
        val background = background
        if (background is RippleDrawable) {
            val newBackground = background.mutate() as RippleDrawable
            if (color != 0)
                newBackground.setColor(ColorStateList.valueOf(color))
            this.background = newBackground
        } else {
            if (color == 0)
                ViewCompat.setBackgroundTintList(this, null)
            else
                ViewCompat.setBackgroundTintList(this, ColorStateList.valueOf(color))
        }
    }
    

    使用方法:

    yourView.setBackgroundTintColor(0xffff0000.toInt())
    

    并且要恢复到正常状态:
    yourView.setBackgroundTintColor(0)
    

    如你所见,你应该知道使用它可能会让视图有一个新的背景,可惜。

    -1
    使用foreground属性作为selectableItemBackground, background属性作为您想要的颜色。
    android:foreground="?attr/selectableItemBackground"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:background="@color/white"
    

    1
    通过这种方式,您将无法更改涟漪效果的颜色。问题是 - “在使用?attr/selectableItemBackground作为背景时,如何修改涟漪颜色?” - HB.

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