Как программно добавить оттенок кнопок


121

В новой библиотеке 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.
Шардж

1
Пожалуйста, проверьте этот ответ .
Амит Вагела

Ответы:


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.
Шардж

30
Библиотека поддержки 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, 01

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
не могли бы вы предоставить полный код для установки оттенка с помощью метода ur?
М. Усман Хан

Лучший ответ...!
Gokul Nath KP

62

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

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

Намного лучше использовать его таким образом, так что вы получите обратную совместимость с API 4!
xarlymg89,

одно из лучших решений.
Атиф Аббаси,

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

Работал у меня. Спасибо.
Уэсли Фрэнкс 06

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
Nashe

1
кнопка. setBackgroundTintList (ContextCompat.getColorStateList (контекст, R.color.blue)); работал у меня
джесто пол


5

Вы можете использовать DrawableCompat, например

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

и если вы хотите изменить цвет, вот код в Kotlin, он не устарел и может использоваться до Android 21:

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

Есть ли аналогичный для самого оттенка текста?
разработчик Android

вы имеете в виду текст как кнопку и хотите изменить цвет фона?
Амин Кешаварзян

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.
Саураб Сингх

Ну ладно, я не знал об этом. Но OP просит Button. Можете ли вы отредактировать свой ответ, указав эту деталь, чтобы я мог снять свой голос против?
Джереми

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>

Использование этого в качестве фона из xml отлично работает на Android 5.0 и всем остальном. Однако, если я попытаюсь установить это в таком коде:

(Не делай этого)

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

На самом деле не имеет значения, передаю ли я Activity или контекст кнопки методу ContextCompat.getColorStateList (), ни один из них не даст мне правильный список состояний цвета по отношению к теме, внутри которой находится кнопка. Это связано с тем, что использование атрибутов темы в списках состояний цвета не поддерживалось до тех пор, пока api 23 и ContextCompat не сделали ничего особенного для их решения. Вместо этого вы должны использовать AppCompatResources.getColorStateList (), который выполняет свой собственный синтаксический анализ ресурсов / разрешение атрибутов темы на устройствах <API 23.

Вместо этого вы должны использовать это:

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

TL; DR : используйте AppCompatResources, а не -ContextCompat-, если вам понадобятся разрешенные тематические ресурсы во всех версиях API Android.

Дополнительные сведения по теме см. В этой статье .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.