it-roy-ru.com

Влияние материала на кнопку с цветом фона

Я использую библиотеку поддержки Android v21. 

Я создал кнопку с пользовательским цветом фона. Эффекты дизайна материала, такие как рябь, раскрытие, исчезли (за исключением повышения при нажатии), когда я использую фоновый цвет.

 <Button
 style="?android:attr/buttonStyleSmall"
 Android:background="?attr/colorPrimary"
 Android:textColor="@color/white"
 Android:textAllCaps="true"
 Android:layout_width="fill_parent"
 Android:layout_height="wrap_content"
 Android:text="Button1"
 />

Background Следующая обычная кнопка, и эффекты работают просто отлично.

<Button
 style="?android:attr/buttonStyleSmall"
 Android:layout_width="fill_parent"
 Android:layout_height="wrap_content"
 Android:textAllCaps="true"
 Android:text="Button1"
/>

Default button

226
Sathesh

Когда вы используете Android:background, вы заменяете большую часть стиля и внешнего вида кнопки пустым цветом.

Update: Начиная с версии 23.0.0 of AppCompat , есть новый стиль Widget.AppCompat.Button.Colored , который использует colorButtonNormal вашей темы для отключенного цвета и colorAccent для включенного цвета ,.

Это позволяет применить его к вашей кнопке напрямую через

<Button
  ...
  style="@style/Widget.AppCompat.Button.Colored" />

Если вам нужен пользовательский colorButtonNormal или colorAccent, вы можете использовать ThemeOverlay, как описано в этот pro-tip и Android:theme на кнопке.

Предыдущий ответ

Вы можете использовать drawable в вашем каталоге v21 для вашего фона, таких как:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:color="?attr/colorControlHighlight">
    <item Android:drawable="?attr/colorPrimary"/>
</ripple>

Это обеспечит цвет фона ?attr/colorPrimary и анимацию ряби по умолчанию с использованием ?attr/colorControlHighlight по умолчанию (который вы также можете установить в своей теме, если хотите).

Примечание: вам придется создать пользовательский селектор для менее чем v21:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:drawable="@color/primaryPressed" Android:state_pressed="true"/>
    <item Android:drawable="@color/primaryFocused" Android:state_focused="true"/>
    <item Android:drawable="@color/primary"/>
</selector>

Предполагая, что у вас есть несколько цветов, которые вы хотели бы использовать для состояния по умолчанию, нажатия и фокусировки. Лично я снял скриншот пульсации на полпути, будучи выбранным, и вытащил из этого основное/сфокусированное состояние.

417
ianhanniballake

Есть еще одно простое решение - создать собственный фон для «плоских» кнопок, сохраняя их «материальные» эффекты.

  1. Поместите свою кнопку в ViewGroup с нужным фоном, установленным там
  2. set selectableItemBackground из текущей темы в качестве фона для вашей кнопки (API> = 11)

т.е.

<FrameLayout
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:background="@color/blue">
    <Button
        style="?android:attr/buttonStyleSmall"
        Android:background="?android:attr/selectableItemBackground"
        Android:textColor="@Android:color/white"
        Android:textAllCaps="true"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:text="Button1"
        />
</FrameLayout>

Может использоваться для кнопок Flat , он работает с API> = 11, и вы получите эффект пульсации на> = 21 устройствах, сохраняя обычные кнопки до 21, пока AppCompat не будет обновлен для поддержки пульсации там.

Вы также можете использовать только кнопки selectableItemBackgroundBorderless для> = 21.

90
kiruwka

Вот простой и обратно совместимый способ создания эффекта ряби для рельефных кнопок с пользовательским фоном.

Ваш макет должен выглядеть так

<Button
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:background="@drawable/my_custom_background"
    Android:foreground="?android:attr/selectableItemBackground"/>
83
Bolein95

Я столкнулся с этой проблемой сегодня, фактически играя с библиотекой v22. 

Предполагая, что вы используете стили, вы можете установить свойство colorButtonNormal, и кнопки будут использовать этот цвет по умолчанию. 

<style name="AppTheme" parent="BaseTheme">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/primaryColor</item>
    <item name="colorPrimaryDark">@color/primaryColorDark</item>
    <item name="colorAccent">@color/accentColor</item>
    <item name="colorButtonNormal">@color/primaryColor</item>
</style>

Помимо этого, вы все равно можете создать стиль для кнопки, а затем использовать ее для каждой кнопки, если вам нужен ассортимент цветов (не проверял, просто размышлял).

Не забудьте добавить Android: перед именами элементов в вашем стиле v21

25
Robert Rose

С AppCompat (22.1.1+) вы можете добавить такой стиль:

<style name="MyGreenButton">
    <item name="colorButtonNormal">#009900</item>
</style>

И используйте его, просто применив стиль:

<Android.support.v7.widget.AppCompatButton
    style="@style/MyGreenButton"
    Android:layout_width="match_width"
    Android:layout_height="wrap_content"
    Android:text="A Green Button"
    />

Программно меняя цвет, я обнаружил, что единственный способ обновить цвет (в API 15 или 16) - это использовать «список оттенков фона». И это не удаляет радиальную анимацию Nice на устройствах API 21:

ColorStateList colorStateList = new ColorStateList(new int[][] {{0}}, new int[] {0xFF009900}); // 0xAARRGGBB
button.setSupportBackgroundTintList(colorStateList);

Потому что button.setBackground(...) и button.getBackground().mutate().setColorFilter(...) не меняют цвет кнопки в API 15 и 16, как в API 21.

24
Robert

Ответ @ ianhanniballake абсолютно правильный и простой. Но мне потребовалось несколько дней, чтобы понять. Для тех, кто не понимает его ответ, здесь более подробно реализация

<Button
        Android:id="@+id/btn"
        style="@style/MaterialButton"
        ... />


<style name="MaterialButton" parent="Widget.AppCompat.Button.Colored">
    <item name="Android:theme">@style/Theme.MaterialButton</item>
   ...
</style>


<style name="Theme.MaterialButton" parent="YourTheme">
    <item name="colorAccent">@color/yourAccentColor</item>
    <item name="colorButtonNormal">@color/yourButtonNormalColor</item>
</style>

=== Или ===

<Button
        Android:id="@+id/btn"
        style="@style/Widget.AppCompat.Button.Colored"
        Android:theme="@style/Theme.MaterialButton" />

<style name="Theme.MaterialButton" parent="YourTheme">
    <item name="colorAccent">@color/yourAccentColor</item>
    <item name="colorButtonNormal">@color/yourButtonNormalColor</item>
</style>
20
Frank Nguyen

Я использовал backgroundTint и передний план:

<Button
    Android:layout_width="match_parent"
    Android:layout_height="40dp"
    Android:backgroundTint="@color/colorAccent"
    Android:foreground="?android:attr/selectableItemBackground"
    Android:textColor="@Android:color/white"
    Android:textSize="10sp"/>
13
SpyZip

Если вы заинтересованы в ImageButton, вы можете попробовать эту простую вещь:

<ImageButton
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:src="@Android:drawable/ic_button"
    Android:background="?attr/selectableItemBackgroundBorderless"
/>
6
Ameer Khalifullah

Я пришел к этому сообщению в поисках способа получить цвет фона моего элемента ListView, но при этом сохранить пульсацию.

Я просто добавил свой цвет в качестве фона и selectableItemBackground в качестве переднего плана:

<style name="my_list_item">
    <item name="Android:background">@color/white</item>
    <item name="Android:foreground">?attr/selectableItemBackground</item>
    <item name="Android:layout_height">@dimen/my_list_item_height</item>
</style>

и это работает как шарм. Я предполагаю, что та же самая техника могла бы использоваться и для кнопок. Удачи :)

6
Joakim

Используйте backgroundTint вместо background

5
shem

v22.1 из appcompat-v7 представил некоторые новые возможности. Теперь можно назначить конкретную тему только одному представлению.

Устаревшее использование app: тема для оформления панели инструментов. Теперь вы можете использовать Android: тема для панелей инструментов на всех устройствах API уровня 7 и выше и Android: поддержка тем для всех виджетов на уровне API 11 и выше устройства.

Таким образом, вместо установки желаемого цвета в глобальной теме, мы создаем новую и назначаем ее только для Button

Пример:

<style name="MyColorButton" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorButtonNormal">@color/myColor</item>
</style>

И используйте этот стиль в качестве темы вашего Button

<Button
 style="?android:attr/buttonStyleSmall"
 Android:layout_width="fill_parent"
 Android:layout_height="wrap_content"
 Android:text="Button1"
 Android:theme="@style/MyColorButton"/>
5
Bhargav Pandit

Если вы в порядке с использованием сторонней библиотеки, проверьте traex/RippleEffect . Это позволяет вам добавить эффект Ripple к ЛЮБОМУ представлению всего несколькими строками кода. Вам просто нужно обернуть в свой файл макета xml элемент, который вы хотите иметь волновой эффект с контейнером com.andexert.library.RippleView

В качестве дополнительного бонуса требуется Min SDK 9, так что вы можете иметь согласованность дизайна в разных версиях ОС.

Вот пример, взятый из репозитория GitHub библиотек:

<com.andexert.library.RippleView
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:rv_centered="true">

    <ImageView
        Android:layout_width="100dp"
        Android:layout_height="100dp"
        Android:src="@Android:drawable/ic_menu_edit"
        Android:background="@Android:color/holo_blue_dark"/> 

</com.andexert.library.RippleView>

Вы можете изменить цвет пульсации, добавив этот атрибут в элемент RippleView: app:rv_color="@color/my_fancy_ripple_color

3
guy.gc
<Android.support.v7.widget.AppCompatButton
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:backgroundTint="#fff"
    Android:textColor="#000"
    Android:text="test"/>

Использование 

xmlns:app="http://schemas.Android.com/apk/res-auto"

и цвет примет на пре-лолипоп

3
André Bäuml

Алекс Локвуд объясняет два подхода, описанных в этом замечательном учебнике: http://www.androiddesignpatterns.com/2016/08/coloring-buttons-with-themeoverlays-background-tints.html :

Подход № 1. Изменение цвета фона кнопки с помощью ThemeOverlay

<!-- res/values/themes.xml -->
<style name="RedButtonLightTheme" parent="ThemeOverlay.AppCompat.Light">
    <item name="colorAccent">@color/googred500</item>
</style>

<Button
    style="@style/Widget.AppCompat.Button.Colored"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:theme="@style/RedButtonLightTheme"/>

Подход № 2. Настройка фонового оттенка AppCompatButton

<!-- res/color/btn_colored_background_tint.xml -->
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <!-- Disabled state. -->
    <item Android:state_enabled="false"
          Android:color="?attr/colorButtonNormal"
          Android:alpha="?android:attr/disabledAlpha"/>

    <!-- Enabled state. -->
    <item Android:color="?attr/colorAccent"/>

</selector>

<Android.support.v7.widget.AppCompatButton
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:backgroundTint="@color/btn_colored_background_tint"/>
2
makovkastar

Программно применяя цвета:

if (Android.os.Build.VERSION.SDK_INT >= Android.os.Build.VERSION_CODES.Lollipop) {

    ColorStateList colorStateListRipple = new ColorStateList(
            new int[][] {{0}},
            new int[] {Color.WHITE} // ripple color
            );

    RippleDrawable rippleDrawable = (RippleDrawable) myButton.getBackground();
    rippleDrawable.setColor(colorStateListRipple);
    myButton.setBackground(rippleDrawable); // applying the ripple color
}

ColorStateList colorStateList = new ColorStateList(
        new int[][]{
                new int[]{Android.R.attr.state_pressed}, // when pressed
                new int[]{Android.R.attr.state_enabled}, // normal state color
                new int[]{} // normal state color
        },
        new int[]{
                Color.CYAN, // when pressed
                Color.RED, // normal state color
                Color.RED // normal state color
        }
);

ViewCompat.setBackgroundTintList(myButton, colorStateList); // applying the state colors
0
Marlon