Как я могу изменить цвет ряби при использовании? Attr/selectableItemBackground в качестве фона?

Я видел некоторые вопросы SO, и они дали несколько возможных методов для достижения того, что я хочу. Например:

  1. использование colorControlHighlight атрибут в styles.xml.

    Вот мой файл 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(no android: prefix)"или измените на ?android:attr/selectableItemBackgroundни то, ни другое не полезно.

  2. использование backgroundTint атрибут в макете.

    Итак, я добавляю android:backgroundTint="#5677FC" к моему TextView, Все еще бесполезно. Затем я попытался изменить android:backgroundTintMode в src_in а также src_atopи они никогда не имеют значения.

Итак, как я могу изменить цвет пульсации, когда я использую ?attr/selectableItemBackground в качестве фона. Я сосредоточен только на Lollipop и выше. Заранее спасибо!

10 ответов

Решение

Наконец я нахожу решение: вместо того, чтобы использовать android:colorControlHighlight прямо в теме SelectableItemBackground Я должен написать другой стиль:

<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>

Наконец добавить style="@style/SelectableItemBackground" в View в layout.xml.

ОБНОВЛЕНО 2016/8/26 После выпуска N я обнаружил, что иногда мы не можем использовать этот метод для установки цвета ряби для некоторого вида View (например, CardView). Теперь я настоятельно рекомендую разработчикам, использующим RippleDrawable, который также может быть объявлен в XML. Вот пример:

Я хочу показать волновой эффект, когда пользователь касается / щелкает CardView выше API21, и, конечно, должен быть другой вид обратной связи перед Lollipop. Поэтому я должен написать:

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

а также selectable_item_background в drawable папка:

<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>

selectable_item_background в drawable-v21 папка:

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

наконец, ripple_black в drawable (или же drawable-v21) папка:

<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", Не забудьте установить OnClickListener, OnTouchListener или что-то подобное для них, иначе рябь не покажет.

Пульсация на устройствах pre и Lollipop+

Харран и Лютинг правы. Принятый ответ - не лучший способ. Позвольте мне показать в коде, как изменить цвет пульсации для версий до Lollipop и выше

  1. Ваша AppTheme должна наследоваться от любой темы AppCompat и содержать атрибут colorControlHighlight (без префикса "android:")

    <!-- Application theme. -->
    <style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
    <item name="colorControlHighlight">#40ffffff</item>
    </style>
    
  2. Ваше представление должно содержать clickable="true" (или должен иметь прослушиватель кликов, установленный программно), а фон должен быть "? Attr/selectableItemBackgroundBorderless" или "? Attr/selectableItemBackground":

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

Обратите внимание: если ваш родительский вид имеет белый фон, вы не увидите эффект ряби, так как он белый. Изменить значение colorControlHighlight для другого цвета

Кроме того, если вы хотите использовать разные цвета пульсации для разных действий, вы можете установить индивидуальную тему для каждого действия в файле манифеста, например:

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

Разные цвета ряби для разных фрагментов в одной и той же деятельности?

Вы можете изменить атрибуты темы деятельности для каждого фрагмента во время выполнения. Просто перезапишите их, прежде чем фрагмент будет заполнен вашим собственным стилем и примените к текущей теме:

в 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;
    }

Этот стиль будет работать только для этого фрагмента


Различный цвет пульсации для разных видов? (Леденец +)

Вы можете изменить цвет пульсации для каждого вида отдельно, используя colorControlHighlight атрибут, он не работает, если вы примените их к представлению напрямую:

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

Вы должны применить это как тему:

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

PS Кроме того, иногда этот подход помогает, если у вас есть неизвестные проблемы с пульсацией, и вы не можете понять это. В моем случае я использовал стороннюю скользящую библиотеку, которая испортила волновые эффекты для всего макета и явно добавила эту тему ко всем интерактивным представлениям, разработанным для меня.

Он показывает эффект ряби с цветом API +21 и простой серый фон при печати для 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" />

Используйте следующие шаги:

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 вызывает выбираемый атрибут по умолчанию для andorid.

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>

Принятый ответ неверен.

Правильный способ использования - это то, что Liuting упомянул в комментарии. использование colorControlHighlight вместо android:colorControlHighlight для изменения по умолчанию colorControlHighlight от AppCompat

* Пожалуйста, обратитесь к http://android-developers.blogspot.co.uk/2014/10/appcompat-v21-material-design-for-pre.html в разделе Темы *

Используйте атрибут переднего плана в качестве selectableItemBackground и атрибут фона в качестве нужного цвета.

android:foreground="?attr/selectableItemBackground"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:background="@color/white"

Этот код работает для меня, чтобы создать рябь:

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. Вот почему я сделал это, как указано выше.

В темной черной (или любой другой) программе попробуйте использовать, как показано ниже ripple_effect.xml в drawable папку и добавить код, как

<?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>

затем установите фон для любого вида как Linear layout, Button, TextView и т.п.

 <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" />

Если вы хотите сделать это программно, это решение, над которым я работал, должно работать, по крайней мере, в большинстве случаев:

      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)

Как видите, вы должны знать, что, к сожалению, его использование может привести к тому, что у представления появится новый фон.

В вашем наборе 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.