Як додати відтінок кнопки програмно


120

У новій бібліотеці AppCompat ми можемо підфарбувати кнопку таким чином:

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/follow"
    android:id="@+id/button_follow"
    android:backgroundTint="@color/blue_100"
    />

Як я можу програмно встановити відтінок кнопки програмно? Я в основному намагаюся реалізувати умовне забарвлення кнопки на основі деякого введення користувача.


Ви впевнені в android: backgroundTint працює над Pre-Lollipop? Я тестую як Button, так і ApCompatButton, але backgroundTint, здається, працює лише на Lollipop.
Шарж

Відповіді:


162

Згідно документації , відповідний метод android:backgroundTintє setBackgroundTintList (список ColorStateList)

Оновлення

Перейдіть за цим посиланням, щоб дізнатися, як створити ресурс списку кольорових держав.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:color="#your_color_here" />
</selector>

потім завантажте його за допомогою

setBackgroundTintList(contextInstance.getResources().getColorStateList(R.color.your_xml_name));

де contextInstanceє примірник аContext


за допомогою AppCompart

btnTag.setSupportButtonTintList(ContextCompat.getColorStateList(Activity.this, R.color.colorPrimary));

який є не кольором, а ColorStateList. Як це використовувати?
Стефан

4
Я розумію, як це зробити зараз завдяки, але чому Android не дозволить вам просто використовувати колір вручну? Для кожного кольору кожної кнопки, яку я маю, я повинен створити xml для ColorStateList? Мені це здається марним
Стефан

2
setBackgroundTintList потребує API 21, навіть якщо ви називаєте його в AppCompatButton.
Шарж

29
Бібліотека підтримки AppCompat пропонує статичний помічник: ViewCompat.setBackgroundTintList(View, ColorStateList)його можна використовувати аж до API 4. Але він працює лише для представлень, які реалізуються TintableBackgroundView, наприклад AppCompatButton(замість звичайних Button).
Джон Адамс

1
Тепер використання ViewCompat.setBackgroundTintList(View, ColorStateList), як запропонував @Jon Adams, має ще більше сенсу, оскільки View.setSupportButtonTintList обмежений RestrictToанотацією. Докладніше тут: developer.android.com/reference/android/support/annotation/…
AlexKost

75

Ви можете використовувати

button.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(R.id.blue_100)));

Але я б рекомендував вам скористатись бібліотекою підтримки для малювання, яка щойно вийшла вчора:

Drawable drawable = ...;

// Wrap the drawable so that future tinting calls work
// on pre-v21 devices. Always use the returned drawable.
drawable = DrawableCompat.wrap(drawable);

// We can now set a tint
DrawableCompat.setTint(drawable, Color.RED);
// ...or a tint list
DrawableCompat.setTintList(drawable, myColorStateList);
// ...and a different tint mode
DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_OVER);

Більше ви можете знайти в цій публікації в блозі (див. Розділ "Мальовнича тонування")


2
Ви можете надати повний код для встановлення відтінку методом ур?
М. Усман Хан

Найкраща відповідь ...!
Gokul Nath KP

60

Схоже, у видах є власна механіка управління відтінком, тому краще буде розміщено список відтінків:

ViewCompat.setBackgroundTintList(
    editText, 
    ColorStateList.valueOf(errorColor));

Набагато краще використовувати цей спосіб, так що ви отримуєте зворотну сумісність від API 4!
xarlymg89

одне з найкращих рішень.
Atif AbbAsi

21

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

    Drawable buttonDrawable = button.getBackground();
    buttonDrawable = DrawableCompat.wrap(buttonDrawable);
    //the color is a direct color int and not a color resource
    DrawableCompat.setTint(buttonDrawable, Color.RED);
    button.setBackground(buttonDrawable);

Це рішення призначено для сценарію, коли в якості фону кнопки використовується малювальний текст. Він працює і на пристроях до Lollipop.


@TruptiNasit Радий почути це.
Shayne3000

Працювали для мене. Дякую.
Wesley Franks

1
@wesleyfranks Запрошуємо вас. Радий почути, що це спрацювало.
Shayne3000

7

Ви пробували щось подібне?

button.setBackgroundTintList(getResources().getColorStateList(R.id.blue_100));

зауважте, що getResources () працюватиме лише в діяльності. Але його можна назвати і в кожному контексті.


Ви можете створити xml, як описано тут: developer.android.com/reference/android/content/res/…
Кріс К.

Очевидно, що getColorStateList застарілий.
cloudsurfin

1
setBackgroundTintList , здається, вимагає рівня API 21
Нашої

1
кнопка. setBackgroundTintList (ContextCompat.getColorStateList (контекст, R.color.blue)); працював на мене
jesto paul


5

Ви можете використовувати DravableCompat, наприклад

public static Drawable setTint(Drawable drawable, int color) {
    final Drawable newDrawable = DrawableCompat.wrap(drawable);
    DrawableCompat.setTint(newDrawable, color);
    return newDrawable;
}

5

це легко вирішується в новій кнопці "Матеріал" з бібліотеки дизайну матеріалів, спочатку додайте залежність:

implementation 'com.google.android.material:material:1.1.0-alpha07'

то у своєму XML використовуйте це для своєї кнопки:

<com.google.android.material.button.MaterialButton
    android:id="@+id/accept"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/i_accept"
    android:textSize="18sp"
    app:backgroundTint="@color/grayBackground_500" />

і коли ви хочете змінити колір, ось код у Котліні, він не застарів, і його можна використовувати до Android 21:

accept.backgroundTintList = ColorStateList.valueOf(ResourcesCompat.getColor(resources, 
R.color.colorPrimary, theme))

Чи є подібний для самого відтінку тексту?
андроїд розробник

ти маєш на увазі текст як кнопку і хочеш змінити колір тла?
Амін Кешаварзіан

4

Шлях, який мені вдалося привернути до роботи, був за допомогою використання CompoundButtonCompat.setButtonTintList(button, colour).

Наскільки я розумію, це працює незалежно від версії Android.


3

У мене була схожа проблема. Я хотів пофарбувати складний малювальний фон для подання на основі значення кольору (int). Я досяг успіху за допомогою коду:

ColorStateList csl = new ColorStateList(new int[][]{{}}, new int[]{color});
textView.setBackgroundTintList(csl);

Де колір - це значення int, що представляє необхідний колір. Це являє собою простий xml ColorStateList:

<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:color="color here"/>
</selector>

Сподіваюся, це допомагає.


2
Мінімально необхідний рівень API 21
forsberg

добре ви могли просто скористатисяColorStateList.valueOf(ColorInt)
user924

2

Для ImageButton ви можете використовувати:

favoriteImageButton.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint

setColorFilter не визначено для кнопок
Jérémy

Це для ImageButton.
Саураб Сінгх,

Ну добре, я не знав про це. Але ОП просить Кнопку. Чи можете ви відредагувати свою відповідь цією деталлю, щоб я міг видалити свій запис?
Jérémy

2

Якщо ви використовуєте Kotlinта Material Design, ви можете змінити такий колір MaterialButton:

myButton.background.setTintList(ContextCompat.getColorStateList(context, R.color.myColor))

Ви можете вдосконалити її ще краще, створивши функцію розширення для свого MaterialButton, щоб зробити код більш читабельним, а ваше кодування трохи зручнішим:

fun MaterialButton.changeColor(color: Int) {
    this.background.setTintList(ContextCompat.getColorStateList(context, color))
}

Потім ви можете використовувати свою функцію скрізь так:

myButton.changeColor(R.color.myColor)

1

На додаток до відповіді Shayne3000 ви можете також використовувати кольоровий ресурс (не лише кольоровий int). Версія Котліна :

var indicatorViewDrawable = itemHolder.indicatorView.background
indicatorViewDrawable = DrawableCompat.wrap(indicatorViewDrawable)
val color = ResourcesCompat.getColor(context.resources, R.color.AppGreenColor, null) // get your color from resources
DrawableCompat.setTint(indicatorViewDrawable, color)
itemHolder.indicatorView.background = indicatorViewDrawable

0

Пропонована відповідь тут не працює належним чином на Android 5.0, якщо ваш список кольорів на основі XML посилається на тематичні атрибути. Наприклад, у мене є список стану кольорів у форматі XML на зразок:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="?colorPrimary" android:state_enabled="true"/>
    <item android:alpha="0.12" android:color="?attr/colorOnSurface"/>
</selector>

Використовуючи це як мій backgroundTint від xml, добре працює на android 5.0 та все інше. Однак якщо я спробую встановити це в такому коді:

(Не робіть цього)

myButton.setSupportButtonTintList(ContextCompat.getColorStateList(myButton.getContext(), R.color.btn_tint_primary));

Насправді неважливо, чи я передаю активність або контекст кнопки методу ContextCompat.getColorStateList (), і не дасть мені належного списку стану кольорів щодо теми, в якій знаходиться кнопка. Це тому, що використання атрибутів теми у списках кольорів не підтримувалось до 23 квітня, і ContextCompat не зробить нічого особливого для їх вирішення. Натомість ви повинні використовувати AppCompatResources.getColorStateList (), який робить власний розбір ресурсів / атрибут теми на пристроях <API 23.

Натомість ви повинні використовувати це:

myButton.setSupportBackgroundTintList(AppCompatResources.getColorStateList(myButton.getContext(), R.color.btn_tint_primary));

TLDR: використовуйте AppCompatResources, а не -ContextCompat-, якщо вам потрібні вирішені тематичні ресурси для всіх версій API для Android.

Більш детальну інформацію по темі див. У цій статті .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.