Вплив матеріалу на кнопку з кольором тла


246

Я використовую бібліотеку підтримки 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"
 />

Фон Далі йде звичайна кнопка, і ефекти працюють просто чудово.

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

Кнопка за замовчуванням


9
Це відбувається тому, що ви замінюєте фон усіма приємними матеріальними ефектами суцільним кольором. Щодо того, як ви правильно розфарбуєте кнопку, зберігаючи Матеріальні ефекти, ніхто з SO ще не зміг цього розібратися.
Натан Уолтерс

2
@SweetWisher Пульсація та інші ефекти не застосовуються кнопкою, коли я змінюю колір тла.
Sathesh

1
@NathanWalters Але сірий колір за замовчуванням некрасивий. :-(
Sathesh

6
Повірте, я знаю ... Ми будемо мати велику заборгованість перед тим, хто придумає, як це зробити правильно.
Натан Уолтерс

1
Дивовижний відповідь stackoverflow.com/a/32238489/1318946
Pratik Butani

Відповіді:


431

Під час використання android:backgroundви замінюєте велику частину стилю і виглядаєте і відчуваєте кнопку з порожнім кольором.

Оновлення: Як в випуск версії 23.0.0 від AppCompat , є новий Widget.AppCompat.Button.Coloredстиль , який використовує вашу тема colorButtonNormalдля інвалідів кольору іcolorAccent для задіяного кольору.

Це дозволяє застосувати його до своєї кнопки безпосередньо через

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

Якщо вам потрібен користувальницький colorButtonNormalабо colorAccent, ви можете скористатись ThemeOverlayописаним у цій підказці та android:themeна кнопці.

Попередній відповідь

Ви можете використовувати малюнок у каталозі 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>

Припустимо, що у вас є кілька кольорів, які вам потрібні для типового, натиснутого та зосередженого стану. Особисто я зробив знімок екрану пульсації посередині, вибравши і витягнув з цього первинний / зосереджений стан.


13
Гарна відповідь! Точно те, що я шукав, однак потрібно було очистити та відновити до того, як проект вирішив визначити схему, що перебуває у dravable-v21.
user1354603


4
@ianhanniballake Цікаво, як поєднати цю техніку роботи, не втрачаючи налаштування закруглених кутів у
тій

3
@ianhanniballake лише коментар, малювання в пульсації під <item android: dravable ... /> не може бути прозорим кольором. У цьому випадку пульсація не відображатиметься. Мені знадобився певний час, щоб зрозуміти це.
Іван Куш

2
У програмі appcompat 23.1.1 та API 22 відключена та увімкнена стан приймає колір темиButtonNormal.
Rémy DAVID

93

Є ще одне просте рішення - забезпечити спеціальний фон для кнопок "Плоскі", зберігаючи їх "Матеріальні" ефекти.

  1. Помістіть кнопку в ViewGroup з потрібним фоном
  2. встановити 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 кнопки.


Ви буквально вигадали про це :-) Хоча це один із способів цього, це може збільшити зв'язок коду, а використання стилів було б рекомендованим способом.
Сатеш

3
Це створює плоску кнопку з кольоровим фоном, так. Але створена кнопка виглядає як квадрат, немає закруглених кутів і тіньових ефектів.
Санкет Берде

7
@SanketBerde Рівно. Тому що це "плоска" кнопка.
kiruwka

2
У первісному питанні не було згадуваного плоского. btw, якщо у вашому рішенні замість <FrameLayout> є батько <CardView>, отримана кнопка буде піднята і матиме тіні. Це працює навіть у попередній льодяниковій версії.
Санкет Берде

1
@SanketBerde чудово знати про CardViewпідхід, дякую за обмін!
kiruwka

88

Ось простий і зворотний сумісний спосіб надати ефект пульсацій піднятим кнопкам на власному тлі.

Ваш макет повинен виглядати приблизно так

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

9
Це найпростіший без суєти спосіб досягти цього. Хороша відповідь.
Тайлер Пфафф

1
api 21+, але не працює. Застосовується на лінійному макеті з істинним натисканням, фон - іншого кольору, вказаний переднім планом.
Алекс

3
Оскільки кнопка є TextView, а не FrameLayout, foregroundне має ефекту до 23. google.com/…
androidguy

2
НІШЕ! Я навіть не знав, що "передній план" був річчю!
Ерік Шленц

2
Працює як шарм ..!
Каннан

25

Я зіткнувся з цією проблемою сьогодні, насправді граючи з бібліотекою 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 .


Про асортимент кольорових кнопок дивіться інші відповіді Роберта: stackoverflow.com/a/31825439/1617737
заборона геоінженерії

Якщо тепер встановлено колір тла, чи є також загальний атрибут, який я можу використовувати у вищевказаному блоці коду для визначення кольору тексту кнопки?
заборона-геоінженерія

24

За допомогою 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) було використання натомість "списку відтінків фону". І це не видаляє приємну радіальну анімацію на пристроях 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.


1
Дуже дякую, він прекрасно працював для мене (навіть якщо використання кнопки у форматі xml, оскільки надувальник AppCompat замінює її на AppCompatButton)
Луї CAD,

1
Використовуйте ColorStateList.valueOf( ... )для побудови простого ColorStateListлише одного кольору.
Тайг

colorAccent і rippleColor не працюють в стилі
Yar

Дякую за цю публікацію Що для мене спрацювало: ViewCompat.setBackgroundTintList(myButton, ColorStateList.valueOf(myColor); Javadoc for setSupportBackgroundTintListкаже, що його слід називати так.
JerabekJakub

22

Відповідь @ 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>

5
Ваша відповідь була для мене останньою частиною головоломки. Можна також написати colorButtonNormalв основній темі @style/AppTheme. Це дає колір за замовчуванням для AppCompat, щоб відповідно розфарбувати кнопки. Тоді ви можете використовувати свою відповідь для тематичного перегляду окремо.
Сіддхарт Пант

1
Є це android:theme="Theme.MaterialButton" чиandroid:theme="@style/Theme.MaterialButton"
osrl

1
@osrl Це android:theme="@style/Theme.MaterialButton". Дякую за вашу правоту.
Френк Нгуен

12

Я використовував фоновий відтінок і передній план:

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

afaik немає необхідності в атрибуті переднього плану, оскільки backgroundTint не перекриває стандартну пульсацію
Julian Os

7

Я прийшов на цю посаду, шукаючи спосіб мати свій фоновий колір ListView предмета, але зберегти пульсацію.

Я просто додав свій колір як фон, а вибірнийItemBackground як передній план:

<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

Якщо вас цікавить ImageButton, ви можете спробувати цю просту річ:

<ImageButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@android:drawable/ic_button"
    android:background="?attr/selectableItemBackgroundBorderless"
/>

5

v22.1з appcompat-v7нових можливостей. Тепер можна призначити певну тему лише одному виду.

Вимкнене використання програми: тема для стилізації Панелі інструментів. Тепер ви можете використовувати 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"/>

4

Якщо ви все добре використовуєте бібліотеку сторонніх розробників, перегляньте traex / RippleEffect . Це дозволяє додати ефект Ripple до будь-якого перегляду лише за допомогою декількох рядків коду. Вам просто потрібно загорнути у свій файл макета xml елемент, на який потрібно мати ефект пульсації з com.andexert.library.RippleViewконтейнером.

Як додатковий бонус, йому потрібно мінімум 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
<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"

і колір буде сприйматися на попередньому льодянику


2

Існує два підходи, пояснені у великому навчальному посібнику: Алекс Локвуд: 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

Програмно застосування кольорів:

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

-1

Я спробував це:

android:backgroundTint:"@color/mycolor"

замість зміни фонової властивості. Це не знімає матеріального ефекту.


Це не спрацює для пристроїв до Lollipop (70% частки ринку). Насправді він отримав підтримку, але Android Studio на сьогоднішній день все ще показує помилки при використанні його без префікса Android.
Сіддхарт Пант
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.