Cómo agregar tinte de botón mediante programación

120

En la nueva biblioteca de AppCompat, podemos teñir el botón de esta manera:

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

¿Cómo puedo configurar el tinte del botón mediante programación en mi código? Básicamente, estoy tratando de implementar una coloración condicional del botón en función de la entrada del usuario.

Stephane
fuente
¿Estás seguro de que android: backgroundTint está funcionando en Pre-Lollipop? Probé tanto con Button como con ApCompatButton, pero backgroundTint solo parece estar funcionando en Lollipop.
Sharj
1
Por favor marque esta respuesta .
Amit Vaghela

Respuestas:

162

De acuerdo con la documentación, el método relacionado android:backgroundTintes setBackgroundTintList (lista ColorStateList)

Actualizar

Siga este enlace para saber cómo crear un recurso de lista de estado de color.

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

luego cárguelo usando

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

donde contextInstancees una instancia de unContext


usando AppCompart

btnTag.setSupportButtonTintList(ContextCompat.getColorStateList(Activity.this, R.color.colorPrimary));
Fuego frío
fuente
que no es un color, sino un ColorStateList. ¿Cómo aprovechar eso?
Stephane
4
Ahora sé cómo hacerlo gracias, pero ¿por qué Android no te permite usar un color manualmente? Para cada color de cada botón que tengo, ¿tendré que crear un xml para ColorStateList? Eso me parece un desperdicio
Stephane
2
setBackgroundTintList necesita API 21 incluso si lo llama en AppCompatButton.
Sharj
29
La biblioteca de soporte de AppCompat ofrece un ayudante estático: ViewCompat.setBackgroundTintList(View, ColorStateList)que se puede usar hasta la API 4. Pero solo funciona para vistas que implementan TintableBackgroundView, por ejemplo AppCompatButton(en lugar de lo habitual Button).
Jon Adams
1
Ahora, el uso ViewCompat.setBackgroundTintList(View, ColorStateList), como sugirió @Jon Adams, tiene aún más sentido ya que View.setSupportButtonTintList está restringido con RestrictToanotaciones. Detalles aquí: developer.android.com/reference/android/support/annotation/…
AlexKost
75

Podrías usar

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

Pero le recomendaría que use un tinte dibujable de biblioteca de soporte que se lanzó ayer:

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

Puede encontrar más en esta publicación de blog (consulte la sección "Tinte dibujable")

dimsuz
fuente
2
¿Podría proporcionar un código completo para configurar el tinte usando su método?
M. Usman Khan
La mejor respuesta...!
Gokul Nath KP
60

Parece que las vistas tienen sus propias mecánicas para la gestión de tintes, por lo que será mejor poner la lista de tintes:

ViewCompat.setBackgroundTintList(
    editText, 
    ColorStateList.valueOf(errorColor));
tse
fuente
¡Es mucho mejor usarlo de esta manera, para que obtenga compatibilidad con versiones anteriores de API 4!
xarlymg89
una de las mejores soluciones.
Atif AbbAsi
21

Para extender correctamente la respuesta de dimsuz proporcionando una situación de código real, consulte el siguiente fragmento de código:

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

Esta solución es para el escenario en el que se utiliza un elemento de diseño como fondo del botón. También funciona en dispositivos anteriores a Lollipop.

Shayne3000
fuente
@TruptiNasit Me alegra escuchar eso.
Shayne3000
Trabajó para mi. Gracias.
Wesley Frank
1
@wesleyfranks De nada. Me alegra saber que funcionó.
Shayne3000
7

¿Has intentado algo como ésto?

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

tenga en cuenta que getResources () solo funcionará en una actividad. Pero también se puede utilizar en cualquier contexto.

Chris K.
fuente
Puede crear un xml como se describe aquí: developer.android.com/reference/android/content/res/…
Chris K.
getColorStateList parece estar en desuso.
cloudsurfin
1
setBackgroundTintList parece requerir API nivel 21
Nashe
1
botón. setBackgroundTintList (ContextCompat.getColorStateList (contexto, R.color.blue)); trabajó para mí
jesto paul
6

así es como se hace en kotlin:

view.background.setTint(ContextCompat.getColor(context, textColor))
Amin Keshavarzian
fuente
gracias, funcionó bien!
Stoica Mircea
5

Puede utilizar DrawableCompat por ejemplo

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

esto se maneja fácilmente en el nuevo Botón Material de la biblioteca de diseño de materiales, primero, agregue la dependencia:

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

luego en su XML, use esto para su botón:

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

y cuando desee cambiar el color, aquí está el código en Kotlin, no está obsoleto y se puede usar antes de Android 21:

accept.backgroundTintList = ColorStateList.valueOf(ResourcesCompat.getColor(resources, 
R.color.colorPrimary, theme))
Amin Keshavarzian
fuente
¿Existe uno similar para el tinte del texto?
desarrollador de Android
¿Te refieres al texto como un botón y quieres cambiar el color del fondo?
Amin Keshavarzian
4

La forma en que logré hacer que el mío funcione fue usando CompoundButtonCompat.setButtonTintList(button, colour).

A mi entender, esto funciona independientemente de la versión de Android.

Matt Jenje
fuente
3

Tuve un problema similar. Quería colorear un fondo dibujable complejo para una vista basada en un valor de color (int). Tuve éxito usando el código:

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

Donde color es un valor int que representa el color requerido. Esto representa el xml ColorStateList simple:

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

Espero que esto ayude.

Muestra tu trabajo
fuente
2
Nivel mínimo de API requerido 21
forsberg
bueno, podrías usarloColorStateList.valueOf(ColorInt)
user924
2

Para ImageButton puede usar:

favoriteImageButton.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint
Saurabh Singh
fuente
setColorFilter no está definido para Buttons
Jérémy
Lo es, para ImageButton.
Saurabh Singh
Oh, ok, no lo sabía. Pero OP está pidiendo Button. ¿Puedes editar tu respuesta con este detalle para que pueda eliminar mi voto negativo?
Jérémy
2

Si está usando Kotliny Material Design, puede cambiar el color de su MaterialButtonasí:

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

Puede mejorarlo aún mejor creando una función de extensión para que su MaterialButtoncódigo sea más legible y su codificación un poco más conveniente:

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

Entonces, puede usar su función en todas partes de esta manera:

myButton.changeColor(R.color.myColor)
Azizjon Kholmatov
fuente
1

Además de la respuesta de Shayne3000 , también puede usar un recurso de color (no solo un color int). Versión de Kotlin :

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
frio abrazo
fuente
0

La respuesta sugerida aquí no funciona correctamente en Android 5.0 si su lista de estado de color basada en XML hace referencia a atributos temáticos. Por ejemplo, tengo una lista de estado de color xml así:

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

Usar esto como backgroundTint de xml funciona bien en Android 5.0 y todo lo demás. Sin embargo, si trato de configurar esto en un código como este:

(No hagas esto)

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

En realidad, no importa si paso la actividad o el contexto del botón al método ContextCompat.getColorStateList (), ni me dará la lista de estado de color adecuada con respecto al tema en el que se encuentra el botón. Esto se debe a que no se admitió el uso de atributos de tema en listas de estado de color hasta api 23 y ContextCompat no hace nada especial para resolverlos. En su lugar, debe usar AppCompatResources.getColorStateList () que realiza su propio análisis de recursos / resolución de atributos de tema en dispositivos <API 23.

En su lugar, debes usar esto:

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

TLDR: use AppCompatResources y no -ContextCompat- si necesita recursos temáticos resueltos en todas las versiones de API de Android.

Para obtener más información sobre el tema, consulte este artículo .

Matt Wolfe
fuente