Alterar a cor "ativada" de um switch


156

Estou usando um controle Switch padrão com o tema holo.light em um aplicativo ICS.

Desejo alterar a cor destacada ou no estado do botão de alternância da luz azul padrão para verde.

Isso deve ser fácil, mas não consigo entender como fazê-lo.


Realmente não vejo outra maneira senão copiar os recursos relevantes da plataforma (seletor e arquivos * .png) e modificar o estado 'on' que pode ser desenhado. Não se esqueça de apontar Switchpara esse seletor personalizado posteriormente.
MH.

Respostas:


100

A partir de agora, é melhor usar o SwitchCompat da biblioteca AppCompat.v7. Você pode usar um estilo simples para alterar a cor dos seus componentes.

values/themes.xml:

<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">@color/my_awesome_color</item>

    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">@color/my_awesome_darker_color</item>

    <!-- colorAccent is used as the default value for colorControlActivated,
         which is used to tint widgets -->
    <item name="colorAccent">@color/accent</item>

    <!-- You can also set colorControlNormal, colorControlActivated
         colorControlHighlight, and colorSwitchThumbNormal. -->

</style>

ref: Blog para desenvolvedores do Android

EDIT :

É a maneira pela qual ela deve ser aplicada corretamente android:theme="@style/Theme.MyTheme" e isso também pode ser aplicado aos estilos-pai, como EditTexts, RadioButtons, Switches, CheckBoxes e ProgressBars:

<style name="My.Widget.ProgressBar" parent="Widget.AppCompat.ProgressBar">

<style name="My.Widget.Checkbox" parent="Widget.AppCompat.CompoundButton.CheckBox">

1
Embora não seja aplicável no momento, esta deve ser a resposta aceita!
Andrew Gallasch

Alteramos isso para a resposta aceita, pois parece a abordagem mais "moderna" para essa pergunta.
JamesSugrue

1
Eu tentei tudo isso e nenhum deles mudou a cor do estado "on" para o meu switch.
Adam Johns

31
'on' é colorAccent, 'off' é colorSwitchThumbNormal. Se AppCompatvocê estiver usando o tema, precisará usar em SwitchCompatvez de Switch. Se você estiver usando o SDK 23+, poderá usar android:thumbTinte android:thumbTintModecom um ColorStateList.
Tom

1
@ TomTz resposta será aquelas coisas 'android: thumbTint' irá funcionar em dispositivos <23
Shirish Herwade

269

Tarde para a festa, mas é assim que eu fiz

Estilo

 <style name="SCBSwitch" parent="Theme.AppCompat.Light">
        <!-- active thumb & track color (30% transparency) -->
        <item name="colorControlActivated">#46bdbf</item>

        <!-- inactive thumb color -->
        <item name="colorSwitchThumbNormal">#f1f1f1
        </item>

        <!-- inactive track color (30% transparency) -->
        <item name="android:colorForeground">#42221f1f
        </item>
    </style>

Cores

insira a descrição da imagem aqui

Layout

<android.support.v7.widget.SwitchCompat
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:checked="false"
    android:theme="@style/SCBSwitch" />

Resultado

Veja a mudança de cores para ativar e desativar a chave

insira a descrição da imagem aqui


14
@MaksimKniazev Você tem que usar SwitchCompat;)
Ovi Trif 04/04

1
Bom, exceto colorControlActivated - ele não define a cor da faixa, apenas a cor do polegar.
Pointer Null

1
aqui é solução para Switch e SwitchCompat: stackoverflow.com/a/47036089/5869630
hosseini roghayeh

As tags <style> precisam ser escritas em res >> values ​​>> styles.xml e na página XML para <Switch ...> você deve adicionar apenas a linha chamada: android: theme = "@ style / SCBSwitch e minhas cores são : colorControlActivated "> # ff0000 e colorSwitchThumbNormal"> # 00ff00 e android: colorForeground "> # 00ff00
Baía

@OviTrif Awesome! É impressionante o quão difícil é encontrar uma informação simples como essa. Muitas e muitas respostas que tenho lido, e ninguém deu uma resposta útil até agora. Finalmente!
jairhumberto

49

Isso está funcionando para mim (requer o Android 4.1):

Switch switchInput = new Switch(this);
int colorOn = 0xFF323E46;
int colorOff = 0xFF666666;
int colorDisabled = 0xFF333333;
StateListDrawable thumbStates = new StateListDrawable();
thumbStates.addState(new int[]{android.R.attr.state_checked}, new ColorDrawable(colorOn));
thumbStates.addState(new int[]{-android.R.attr.state_enabled}, new ColorDrawable(colorDisabled));
thumbStates.addState(new int[]{}, new ColorDrawable(colorOff)); // this one has to come last
switchInput.setThumbDrawable(thumbStates);

Observe que o estado "padrão" precisa ser adicionado por último, como mostrado aqui.

O único problema que vejo é que o "polegar" do comutador agora parece maior que o plano de fundo ou a "faixa" do comutador. Acho que é porque ainda estou usando a imagem da faixa padrão, que tem algum espaço vazio ao redor. No entanto, quando tentei personalizar a imagem da faixa usando essa técnica, minha opção parecia ter uma altura de 1 pixel, com apenas uma fatia do texto ativado / desativado. Deve haver uma solução para isso, mas ainda não a encontrei ...

Atualização para Android 5

No Android 5, o código acima faz a troca desaparecer completamente. Deveríamos poder usar o novo método setButtonTintList , mas isso parece ser ignorado para opções. Mas isso funciona:

ColorStateList buttonStates = new ColorStateList(
        new int[][]{
                new int[]{-android.R.attr.state_enabled},
                new int[]{android.R.attr.state_checked},
                new int[]{}
        },
        new int[]{
                Color.BLUE,
                Color.RED,
                Color.GREEN
        }
);
switchInput.getThumbDrawable().setTintList(buttonStates);
switchInput.getTrackDrawable().setTintList(buttonStates);

Atualização para Android 6-7

Como Cheruby afirmou nos comentários, podemos usar o novo setThumbTintListe que funcionou como esperado para mim. Também podemos usar setTrackTintList, mas isso aplica a cor como uma mistura, com um resultado mais escuro do que o esperado em temas de cores escuras e mais claro que o esperado em temas de cores claras, às vezes a ponto de ficar invisível. No Android 7, consegui minimizar essa alteração substituindo o modo de tonalidade da trilha , mas não consegui resultados decentes no Android 6. Você pode precisar definir cores extras que compensem a mistura. Você já sentiu que o Google não quer que personalizemos a aparência de nossos aplicativos?

ColorStateList thumbStates = new ColorStateList(
        new int[][]{
                new int[]{-android.R.attr.state_enabled},
                new int[]{android.R.attr.state_checked},
                new int[]{}
        },
        new int[]{
                Color.BLUE,
                Color.RED,
                Color.GREEN
        }
);
switchInput.setThumbTintList(thumbStates);
if (Build.VERSION.SDK_INT >= 24) {
    ColorStateList trackStates = new ColorStateList(
            new int[][]{
                    new int[]{-android.R.attr.state_enabled},
                    new int[]{}
            },
            new int[]{
                    Color.GRAY,
                    Color.LTGRAY
            }
    );
    switchInput.setTrackTintList(trackStates);
    switchInput.setTrackTintMode(PorterDuff.Mode.OVERLAY);
}

Estou usando a abordagem getThumbDrawable / getTrackDrawable para criar uma opção em que ambos os estados tenham a mesma cor - em outras palavras, a opção não ativa / desativa algo, mas é usada para uma escolha entre duas alternativas.
Natix

4
Entendemos que DrawableCompat.setTintList permitirá que ele funcione em dispositivos anteriores. Eu chamo: DrawableCompat.setTintList (switchCompat.getThumbDrawable (), foregroundState);
Alexey #

Edite a resposta para incluir a solução DrawableCompat. Funciona perfeitamente!
Dmytro Karataiev 1/11/16

API 23+: também switchInput.setThumbTintList(buttonStates); funciona para o Nougat. API 21-22: use o DrawableCompat conforme sugerido por @Alexey. O switchInput.setButtonTintList(buttonStates);não funcionou para mim, não coloriu os estados do meu Switch. API abaixo de 21: switchInput.getThumbDrawable().setColorFilter(someColor, PorterDuff.Mode.SrcIn); funcionou para mim. Também trabalhei com o Xamarin, então traduza-os para C # nos renderizadores do Android se você usar o Xamarin.Forms.
Cheruby

37

Para alterar o estilo do Switch sem usar o código style.xml ou Java, você pode personalizar o switch no XML do layout:

<Switch
        android:id="@+id/checkbox"
        android:layout_width="wrap_content"
        android:thumbTint="@color/blue"
        android:trackTint="@color/white"
        android:checked="true"
        android:layout_height="wrap_content" />

É atributo android: thumbTint e android: trackTint que permitem personalizar cores

Este é o resultado visual para este XML:

insira a descrição da imagem aqui


17
Isso muda a cor do polegar, não importa se ele está ligado ou desligado.
android developer

1
"O atributo thumbTint é usado apenas no API nível 21 e superior"
norbDEV 29/08/17

6
@norbDEV use app: thumbTint e app: trackTint com o SwitchCompat da biblioteca AppCompat.v7 para obter um nível de API mais baixo.
David Darias 02/03

Isso funciona, mas e se você quiser alterar a cor do polegar, dependendo de estar ligado ou desligado?
TavernSenses

2
Se você quiser usar thumbTint inferior a 21 o uso app:thumbTint, em vez de android:thumbTinte mudança switchcomSwitchCompat
Kavita_p

33

Crie um switch personalizado e substitua setChecked para alterar a cor:

  public class SwitchPlus extends Switch {

    public SwitchPlus(Context context) {
        super(context);
    }

    public SwitchPlus(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SwitchPlus(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setChecked(boolean checked) {
        super.setChecked(checked);
        changeColor(checked);
    }

    private void changeColor(boolean isChecked) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            int thumbColor;
            int trackColor;

            if(isChecked) {
                thumbColor = Color.argb(255, 253, 153, 0);
                trackColor = thumbColor;
            } else {
                thumbColor = Color.argb(255, 236, 236, 236);
                trackColor = Color.argb(255, 0, 0, 0);
            }

            try {
                getThumbDrawable().setColorFilter(thumbColor, PorterDuff.Mode.MULTIPLY);
                getTrackDrawable().setColorFilter(trackColor, PorterDuff.Mode.MULTIPLY);
            }
            catch (NullPointerException e) {
                e.printStackTrace();
            }
        }
    }
}

2
O primeiro post que realmente me ajudou a obter cores personalizadas para o Material Switch sem usar estilos ou temas. Obrigado !
Mackovich

1
Agradável. Eu já tinha meu próprio Switch personalizado, então só precisei substituir o método setChecked e todos eles mudaram suas cores automaticamente. Obrigado da Espanha.
Julio

22

Embora a resposta do SubChord esteja correta, ela realmente não responde à pergunta de como definir a cor "ativada" sem afetar também outros widgets. Para fazer isso, use a ThemeOverlayem styles.xml:

<style name="ToggleSwitchTheme" parent="ThemeOverlay.AppCompat.Light">
    <item name="colorAccent">@color/green_bright</item>
</style>

E referencie-o no seu switch:

<android.support.v7.widget.SwitchCompat
  android:theme="@style/ToggleSwitchTheme" ... />

Ao fazê-lo, afetará SOMENTE a cor das visualizações nas quais você deseja aplicá-la.


Por alguma razão, eu também precisei definir "colorControlActivated" para o mesmo valor, mas no POC, bastava usar "colorAccent". Por quê?
desenvolvedor android

22
<androidx.appcompat.widget.SwitchCompat
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:thumbTint="@color/white"
                app:trackTint="@drawable/checker_track"/>

E dentro do checker_track.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/lightish_blue" android:state_checked="true"/>
    <item android:color="@color/hint" android:state_checked="false"/>
</selector>

thumbTintaplica-se apenas à API 21 do Android e acima. Como se eu quiser mudar a cor abaixo do Android 21?
Giovanka Bisano

developer.android.com/reference/android/support/v7/widget/… O SwitchCompat é compatível com a API 7 e superior
wingear

1
É 2020. Eu realmente me pergunto em que lugar do mundo as pessoas ainda usam o Android 21 e abaixo?
zeeshan 23/04

18

Eu o resolvi atualizando o Filtro de cores quando o estado do comutador foi alterado ...

public void bind(DetailItem item) {
    switchColor(item.toggle);
    listSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                switchColor(b);
        }
    });
}

private void switchColor(boolean checked) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        listSwitch.getThumbDrawable().setColorFilter(checked ? Color.BLACK : Color.WHITE, PorterDuff.Mode.MULTIPLY);
        listSwitch.getTrackDrawable().setColorFilter(!checked ? Color.BLACK : Color.WHITE, PorterDuff.Mode.MULTIPLY);
    }
}

13

Pode ser um pouco tarde, mas para os botões de opção, o botão toogle não é a resposta, você deve alterar o drawable no parâmetro xml da opção:

 android:thumb="your drawable here"

9

tornar drawable "newthumb.xml"

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/Green" android:state_checked="true"/>
    <item android:color="@color/Red" android:state_checked="false"/>
</selector>

e crie drawable "newtrack.xml"

<selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="@color/black" android:state_checked="true"/>
        <item android:color="@color/white" android:state_checked="false"/>
    </selector>

e adicione-o no Switch:

<Switch
        android:trackTint="@drawable/newtrack"
        android:thumbTint="@drawable/newthumb"
         />

1
Isso funciona. No entanto, deve-se notar que o AndroidStudio não poderá sugerir recursos @drawable para trackTintou thumbTint. É preciso escrevê-lo manualmente e ele funciona.
Benjamin Basmaci 24/11/19

Por alguma razão, esta é a única resposta que funciona de maneira confiável no meu Huawei. Obrigado!
einUsername

7

No Android Lollipop e superior, defina-o no seu estilo de tema:

<style name="BaseAppTheme" parent="Material.Theme">
    ...
    <item name="android:colorControlActivated">@color/color_switch</item>
</style>

O problema com esta solução é que ela também altera as cores dos meus textos selecionados, o que não é o que eu quero.
codewing

@ codewing Claro que sim. Porque isso é definido na preferência de estilo global. Para atingir seu objetivo, é encontrar o ID da visualização de destino e modificar seus atributos.
emen

OK, isso é para a posição "On". Que tal mudar a cor do polegar para a posição "Desligado"?
precisa saber é o seguinte

7

Crie sua própria imagem de 9 patches e defina-a como plano de fundo do botão de alternância.

http://radleymarx.com/2011/simple-guide-to-9-patch/


2
Sim, poderia fazer isso, mas certamente deve haver uma maneira mais fácil? Seletores, talvez?
JamesSugrue

Não, não há maneira mais fácil. Você não pode mudar magicamente a cor de uma imagem :)
you786

Bom ponto. Não entendi completamente como funcionou até ter um olhar mais profundo.
JamesSugrue

@ Denizen, você tem certeza? Em caso afirmativo, poste uma resposta e eu votarei nela.
you786

@ Denizen Por favor, remova seu comentário. O Android Switch sempre retorna nulo para getBackground (), perdi 30 minutos tentando isso.
Shirish Herwade

5

A solução sugerida pela arlomedia funcionou para mim. Sobre a questão do espaço extra, resolvi remover todos os revestimentos do interruptor.

EDITAR

Conforme solicitado, aqui está o que eu tenho.

No arquivo de layout, meu switch está dentro de um layout linear e depois de um TextView.

<LinearLayout
        android:id="@+id/myLinearLayout"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center_horizontal|center"
        android:gravity="right"
        android:padding="10dp"
        android:layout_marginTop="0dp"
        android:background="@drawable/bkg_myLinearLayout"
        android:layout_marginBottom="0dp">
        <TextView
            android:id="@+id/myTextForTheSwitch"
            android:layout_height="wrap_content"
            android:text="@string/TextForTheSwitch"
            android:textSize="18sp"
            android:layout_centerHorizontal="true"
            android:layout_gravity="center_horizontal|center"
            android:gravity="right"
            android:layout_width="wrap_content"
            android:paddingRight="20dp"
            android:textColor="@color/text_white" />
        <Switch
            android:id="@+id/mySwitch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textOn="@string/On"
            android:textOff="@string/Off"
            android:layout_centerHorizontal="true"
            android:layout_gravity="center_horizontal"
            android:layout_toRightOf="@id/myTextForTheSwitch"
            android:layout_alignBaseline="@id/myTextForTheSwitch"
            android:gravity="right" />
    </LinearLayout>

Como estou trabalhando com Xamarin / Monodroid (min. Android 4.1), meu código é:

Android.Graphics.Color colorOn = Android.Graphics.Color.Green;
Android.Graphics.Color colorOff = Android.Graphics.Color.Gray;
Android.Graphics.Color colorDisabled = Android.Graphics.Color.Green;

StateListDrawable drawable = new StateListDrawable();
drawable.AddState(new int[] { Android.Resource.Attribute.StateChecked }, new ColorDrawable(colorOn));
drawable.AddState(new int[] { -Android.Resource.Attribute.StateEnabled }, new ColorDrawable(colorDisabled));
drawable.AddState(new int[] { }, new ColorDrawable(colorOff));

swtch_EnableEdit.ThumbDrawable = drawable;

swtch_EnableEdit é definido anteriormente assim (Xamarin):

Switch swtch_EnableEdit = view.FindViewById<Switch>(Resource.Id.mySwitch);

Não defino todos os campos e não chamo .setPadding (0, 0, 0, 0).


Você pode fornecer código para isso? Eu tentei switchInput.setPadding (0, 0, 0, 0), mas nada mudou.
Arlomedia 7/04

1
Testado no Xamarin usando a biblioteca AppCompat para segmentar 5.x e funcionou como anunciado.
Alex.Ritna

4

você pode criar um estilo personalizado para o widget de alternância que usa o acento de cores como padrão ao criar um estilo personalizado para ele.

<style name="switchStyle" parent="Theme.AppCompat.Light">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorPrimary</item>    <!-- set your color -->
</style>    



1

Eu não sei como fazê-lo em java, mas se você tem um estilo definido para o seu aplicativo, você pode adicionar esta linha ao seu estilo e você terá a cor desejada para mim, eu usei # 3F51B5

<color name="ascentColor">#3F51B5</color>

1

A maneira mais fácil é definir o matiz da faixa e definir o modo matiz como src_over para remover 30% de transparência.

android:trackTint="@drawable/toggle_style"
android:trackTintMode="src_over"

toggle_style.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/informationDefault"
        android:state_checked="true"
        />
    <item android:color="@color/textDisabled" android:state_checked="false"/>
</selector>

0

Como complemento às respostas existentes: você pode personalizar o polegar e acompanhar usando seletores na res/colorpasta, por exemplo:

switch_track_selector

<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/lightBlue"
        android:state_checked="true" />
    <item android:color="@color/grey"/>
</selector>

switch_thumb_selector

<selector
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/darkBlue"
        android:state_checked="true" />
    <item android:color="@color/white"/>
</selector>

Use estes seletores para personalizar as tonalidades da faixa e do polegar:

<androidx.appcompat.widget.SwitchCompat
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:trackTint="@color/switch_track_selector"
    app:thumbTint="@color/switch_thumb_selector"/>

Tenha em mente que se você usar Standart Switche androidnamespace para esses atributos, ele só vai funcionar para API 23 e, mais tarde, por isso uso SwitchCompatcom appnamespace xmlns:app="http://schemas.android.com/apk/res-auto"como solução universal.

Resultado:

insira a descrição da imagem aqui


0

No xml, você pode alterar a cor como:

 <androidx.appcompat.widget.SwitchCompat
    android:id="@+id/notificationSwitch"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:checked="true"
    app:thumbTint="@color/darkBlue"
    app:trackTint="@color/colorGrey"/>

Dinamicamente, você pode alterar como:

Switch.thumbDrawable.setColorFilter(ContextCompat.getColor(requireActivity(), R.color.darkBlue), PorterDuff.Mode.MULTIPLY)

-1

Solução para o Android Studio 3.6:

yourSwitch.setTextColor(getResources().getColor(R.color.yourColor));

Altera a cor do texto de a no valor definido no arquivo XML de cores (yourColor).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.