Como adicionar o tom do botão de maneira programática

120

Na nova biblioteca AppCompat, podemos colorir o botão desta forma:

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

Como posso definir a tonalidade do botão programaticamente em meu código? Basicamente, estou tentando implementar uma coloração condicional do botão com base em alguma entrada do usuário.

Stephane
fonte
Tem certeza de que o android: backgroundTint está funcionando no Pré-Lollipop? Eu testo com Button e ApCompatButton, mas backgroundTint só parece funcionar no Lollipop.
Sharj
1
Verifique esta resposta .
Amit Vaghela

Respostas:

162

De acordo com a documentação, o método relacionado android:backgroundTinté setBackgroundTintList (lista ColorStateList)

Atualizar

Siga este link para saber como criar um recurso de lista de estado de cor.

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

então carregue-o usando

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

onde contextInstanceestá uma instância de umContext


usando AppCompart

btnTag.setSupportButtonTintList(ContextCompat.getColorStateList(Activity.this, R.color.colorPrimary));
Fogo frio
fonte
que não é uma cor, mas um ColorStateList. Como aproveitar isso?
Stephane,
4
Eu sei como fazer isso agora, mas por que o Android não permite que você use uma cor manualmente? Para cada cor de cada botão que tenho, terei que criar um xml para um ColorStateList? Isso parece um desperdício para mim
Stephane,
2
setBackgroundTintList precisa da API 21, mesmo se você chamá-la em AppCompatButton.
Sharj
29
A biblioteca de suporte AppCompat oferece um auxiliar estático: ViewCompat.setBackgroundTintList(View, ColorStateList)que pode ser usado desde a API 4. Mas só funciona para visualizações que implementam TintableBackgroundView, por exemplo AppCompatButton(em vez do usual Button).
Jon Adams
1
Agora, usar ViewCompat.setBackgroundTintList(View, ColorStateList), como sugeriu @Jon Adams, faz ainda mais sentido, já que View.setSupportButtonTintList é restrito a RestrictToanotações. Detalhes aqui: developer.android.com/reference/android/support/annotation/…
AlexKost 01 de
75

Você poderia usar

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

Mas eu recomendo que você use uma coloração drawable da biblioteca de suporte que acaba de ser lançada ontem:

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

Você pode encontrar mais nesta postagem do blog (consulte a seção "Tingimento de drawable")

Dimsuz
fonte
2
Você poderia fornecer o código completo para definir a tonalidade usando seu método?
M. Usman Khan
Melhor resposta...!
Gokul Nath KP
60

Parece que as visualizações têm mecânica própria para gerenciamento de tonalidade, então melhor será colocar a lista de tonalidade:

ViewCompat.setBackgroundTintList(
    editText, 
    ColorStateList.valueOf(errorColor));
tse
fonte
É muito melhor usá-lo dessa maneira, para que você obtenha compatibilidade com versões anteriores da API 4!
xarlymg89
uma das melhores soluções.
Atif AbbAsi
21

Para estender adequadamente a resposta de dimsuz fornecendo uma situação de código real, consulte o seguinte trecho 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 solução é para o cenário em que um drawable é usado como plano de fundo do botão. Ele funciona em dispositivos pré-Lollipop também.

Shayne3000
fonte
@TruptiNasit Fico feliz em ouvir isso.
Shayne3000
Funcionou para mim. Obrigado.
wesley franks
1
@wesleyfranks De nada. Fico feliz em saber que funcionou.
Shayne3000 de
7

Você já tentou algo assim?

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

observe que getResources () só funcionará em uma atividade. Mas também pode ser chamado em qualquer contexto.

Chris K.
fonte
Você pode criar um xml conforme descrito aqui: developer.android.com/reference/android/content/res/…
Chris K.
getColorStateList parece estar obsoleto.
cloudsurfin
1
setBackgroundTintList parece requerer API de nível 21
Nashe
1
botão. setBackgroundTintList (ContextCompat.getColorStateList (context, R.color.blue)); trabalhou para mim
jesto paul
6

aqui está como fazer isso em kotlin:

view.background.setTint(ContextCompat.getColor(context, textColor))
Amin Keshavarzian
fonte
obrigado, funcionou muito bem!
Stoica Mircea
5

Você pode usar DrawableCompat, por exemplo

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

isso é facilmente resolvido no novo Botão de material da biblioteca de design de material, primeiro, adicione a dependência:

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

em seguida, em seu XML, use para o botão:

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

e quando você quiser mudar a cor, aqui está o código em Kotlin, ele não está obsoleto e pode ser usado antes do Android 21:

accept.backgroundTintList = ColorStateList.valueOf(ResourcesCompat.getColor(resources, 
R.color.colorPrimary, theme))
Amin Keshavarzian
fonte
Existe um similar para o próprio tom do texto?
desenvolvedor Android de
você quer dizer o texto como um botão e deseja alterar a cor do fundo?
Amin Keshavarzian
4

A maneira como consegui fazer o meu funcionar foi usando CompoundButtonCompat.setButtonTintList(button, colour).

No meu entendimento, isso funciona independentemente da versão do Android.

Matt Jenje
fonte
3

Eu tive um problema parecido. Desejei colorir um fundo de drawable complexo para uma visualização com base em um valor de cor (int). Consegui usar o código:

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

Onde color é um valor interno que representa a cor necessária. Isso representa o xml ColorStateList simples:

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

Espero que isto ajude.

Mostre seu trabalho
fonte
2
Nível mínimo de API exigido 21
forsberg
bem, você poderia apenas usarColorStateList.valueOf(ColorInt)
user924
2

Para ImageButton, você pode usar:

favoriteImageButton.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint
Saurabh Singh
fonte
setColorFilter não está definido para botões
Jérémy
É, para ImageButton.
Saurabh Singh
Oh ok, eu não sabia sobre isso. Mas OP está pedindo Button. Você pode editar sua resposta com este detalhe para que eu possa remover meu voto negativo?
Jérémy
2

Se você estiver usando Kotline Material Design, poderá alterar a cor do seu MaterialButtonassim:

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

Você pode melhorá-lo ainda melhor criando uma função de extensão para o seu MaterialButton, a fim de tornar seu código mais legível e um pouco mais conveniente:

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

Em seguida, você pode usar sua função em qualquer lugar desta forma:

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

Além da resposta de Shayne3000 , você também pode usar um recurso de cor (não apenas uma cor interna ). Versão 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
abraço frio
fonte
0

A resposta sugerida aqui não funciona corretamente no Android 5.0 se sua lista de estados de cores com base em XML faz referência a atributos temáticos. Por exemplo, eu tenho uma lista de estados de cores xml como esta:

<?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 isso como meu backgroundTint de xml funciona muito bem no Android 5.0 e em tudo o mais. No entanto, se eu tentar definir isso em um código como este:

(Não faça isso)

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

Na verdade, não importa se eu passo a Activity ou o contexto do botão para o método ContextCompat.getColorStateList (), nem me dá a lista de estados de cores adequada com relação ao tema do botão. Isso ocorre porque o uso de atributos de tema em listas de estados de cores não era compatível até que a API 23 e o ContextCompat não fizessem nada de especial para resolvê-los. Em vez disso, você deve usar AppCompatResources.getColorStateList (), que faz sua própria análise de recurso / resolução de atributo de tema em dispositivos <API 23.

Em vez disso, você deve usar isto:

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

TLDR: use AppCompatResources e não -ContextCompat- se precisar de recursos temáticos resolvidos em todas as versões de API do Android.

Para obter mais informações sobre o assunto, consulte este artigo .

Matt Wolfe
fonte