Zmień kolor „włączony” przełącznika


156

Używam standardowego elementu sterującego przełącznikiem z motywem holo.light w aplikacji ICS.

Chcę zmienić podświetlony lub włączony kolor przycisku przełącznika ze standardowego jasnoniebieskiego na zielony.

To powinno być łatwe, ale nie mam pojęcia, jak to zrobić.


Naprawdę nie widzę innego sposobu niż skopiowanie odpowiednich zasobów platformy (selektor i pliki * .png) i zmodyfikowanie stanu „on” do rysowania. Nie zapomnij Switchpóźniej wskazać tego selektora niestandardowego.
MH.

Odpowiedzi:


100

Od teraz lepiej jest używać SwitchCompat z biblioteki AppCompat.v7. Następnie możesz użyć prostego stylu, aby zmienić kolor komponentów.

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 deweloperów Androida

EDYCJA :

Sposób, w jaki powinien być poprawnie zastosowany, przebiega android:theme="@style/Theme.MyTheme" i można go również zastosować do stylów nadrzędnych, takich jak EditTexts, RadioButtons, Switches, CheckBoxes i ProgressBars:

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

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

1
Chociaż nie ma to zastosowania w danym momencie, powinna to być akceptowana odpowiedź!
Andrew Gallasch

Zmieniłem to na zaakceptowaną odpowiedź, ponieważ wydaje się, że jest to bardziej „nowoczesne” podejście do tego pytania.
JamesSugrue

1
Wypróbowałem je wszystkie i żaden z nich nie zmienił koloru stanu „włączony” dla mojego przełącznika.
Adam Johns

31
„on” jest colorAccent, „off” jest colorSwitchThumbNormal. Jeśli korzystasz z AppCompatmotywu, musisz użyć SwitchCompatzamiast Switch. Jeśli używasz SDK 23+, możesz używać android:thumbTinti android:thumbTintModez ColorStateList.
Tom

1
@Tom plz odpowie, czy te „android: thumbTint” będą działać na urządzeniach <23
Shirish Herwade,

269

Spóźniony na imprezę, ale tak to zrobiłem

Styl

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

Zabarwienie

wprowadź opis obrazu tutaj

Układ

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

Wynik

Zobacz zmianę kolorów dla włączników i wyłączników

wprowadź opis obrazu tutaj


14
@MaksimKniazev Musisz użyć SwitchCompat;)
Ovi Trif

1
Dobrze, z wyjątkiem colorControlActivated - nie ustawia koloru ścieżki, tylko kolor kciuka.
Pointer Null

1
tutaj jest rozwiązanie dla Switch i SwitchCompat: stackoverflow.com/a/47036089/5869630
roghayeh hosseini

Tagi <style> musiały być zapisane pod res >> values ​​>> styles.xml, a na stronie XML dla <Switch ...> należy dodać tylko linię o nazwie: android: theme = "@ style / SCBSwitch i moje kolory są : colorControlActivated "> # ff0000 i colorSwitchThumbNormal"> # 00ff00 i android: colorForeground "> # 00ff00
Bay

@OviTrif Awesome! To imponujące, jak trudno jest znaleźć taką prostą informację. Wiele, wiele odpowiedzi, które czytałem i do tej pory nikt nie udzielił odpowiedzi roboczej. Wreszcie!
jairhumberto

49

To działa dla mnie (wymaga Androida 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);

Zauważ, że stan „domyślny” należy dodać jako ostatni, jak pokazano tutaj.

Jedynym problemem, jaki widzę, jest to, że „kciuk” przełącznika wydaje się teraz większy niż tło lub „ścieżka” przełącznika. Myślę, że to dlatego, że nadal używam domyślnego obrazu ścieżki, który ma wokół niego puste miejsce. Jednak gdy próbowałem dostosować obraz ścieżki za pomocą tej techniki, mój przełącznik wydawał się mieć wysokość 1 piksela z pojawianiem się tylko kawałka tekstu włączania / wyłączania. Musi być na to rozwiązanie, ale jeszcze go nie znalazłem ...

Aktualizacja dla Androida 5

W systemie Android 5 powyższy kod powoduje całkowite zniknięcie przełącznika. Powinniśmy móc użyć nowej metody setButtonTintList , ale wydaje się, że jest to ignorowane w przypadku przełączników. Ale to działa:

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

Aktualizacja dla Androida 6-7

Jak stwierdził Cheruby w komentarzach, możemy użyć nowego setThumbTintListi działało zgodnie z oczekiwaniami. Możemy również użyć setTrackTintList, ale to powoduje, że kolor jest mieszanką, w wyniku czego jest ciemniejszy niż oczekiwano w motywach o ciemnych kolorach i jaśniejszy niż oczekiwano w motywach o jasnych kolorach, czasem do tego stopnia, że ​​jest niewidoczny. W systemie Android 7 udało mi się zminimalizować tę zmianę, zastępując tryb odcień ścieżki , ale nie mogłem uzyskać przyzwoitych wyników w Androidzie 6. Być może będziesz musiał zdefiniować dodatkowe kolory, które kompensują mieszanie. (Czy kiedykolwiek miałeś wrażenie, że Google nie chce, abyśmy dostosowywali wygląd naszych aplikacji?)

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

Używam metody getThumbDrawable / getTrackDrawable, aby utworzyć przełącznik, w którym oba stany mają ten sam kolor - innymi słowy, przełącznik nie włącza / wyłącza czegoś, ale służy do wyboru między dwiema alternatywami.
Natix

4
Mam, że DrawableCompat.setTintList pozwoli mu działać na poprzednich urządzeniach. Wołam: DrawableCompat.setTintList (switchCompat.getThumbDrawable (), foregroundState);
Alexey

Edytuj odpowiedź, aby uwzględnić rozwiązanie DrawableCompat. Działa idealnie!
Dmytro Karataiev

API 23+: switchInput.setThumbTintList(buttonStates); działa również dla Nougat. API 21-22: użyj DrawableCompat zgodnie z sugestią @Alexey. To switchInput.setButtonTintList(buttonStates);nie działało dla mnie, nie pokolorowało stanów dla mojego Switcha. API poniżej 21: switchInput.getThumbDrawable().setColorFilter(someColor, PorterDuff.Mode.SrcIn); Te działały dla mnie. Pracowałem również z platformą Xamarin, więc przetłumacz je na język C # w mechanizmach renderujących systemu Android, jeśli używasz platformy Xamarin.Forms.
Cheruby

37

Aby zmienić styl przełączania bez używania style.xml lub kodu Java, możesz dostosować przełącznik do formatu XML układu:

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

Jest to atrybut android: thumbTint i android: trackTint, który umożliwia dostosowanie koloru

Oto wizualny wynik dla tego XML:

wprowadź opis obrazu tutaj


17
To zmienia kolor kciuka, bez względu na to, czy jest włączony, czy wyłączony.
programista Androida

1
„Atrybut thumbTint jest używany tylko na poziomie API 21 i wyższym”
norbDEV,

6
@norbDEV użyj app: thumbTint i app: trackTint z SwitchCompat z biblioteki AppCompat.v7 dla niższego poziomu API.
David Darias

To działa, ale co jeśli chcesz zmienić kolor kciuka, w zależności od tego, czy jest włączony, czy wyłączony?
TavernSenses

2
Jeśli chcesz użyć thumbTint poniżej 21, użyj app:thumbTintzamiast android:thumbTinti zmień za switchpomocąSwitchCompat
Kavita_p

33

Utwórz niestandardowy przełącznik i nadpisz zestaw Zaznaczone, aby zmienić kolor:

  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
Pierwszy post, który pomógł mi w uzyskaniu niestandardowego koloru dla przełącznika materiału bez używania stylu lub motywów. Dzięki !
Mackovich

1
Miły. Miałem już własny, dostosowany Switch, więc musiałem tylko nadpisać metodę setChecked i wszystkie automatycznie zmieniły kolory. Dzięki z Hiszpanii.
Julio

22

Chociaż odpowiedź SubChord jest poprawna, tak naprawdę nie odpowiada na pytanie, jak ustawić kolor „włączony” bez wpływu również na inne widżety. Aby to zrobić, użyj a ThemeOverlayw styles.xml:

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

I odwołaj się do tego w swoim przełączniku:

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

W ten sposób wpłynie to TYLKO na kolor widoków, do których chcesz go zastosować.


Z jakiegoś powodu musiałem też ustawić "colorControlActivated" na tę samą wartość, jednak na POC wystarczyło użyć "colorAccent". Dlaczego?
programista Androida

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

A wewnątrz 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>

thumbTintdotyczy tylko Android API 21 i nowszych. Jak, jeśli chcę zmienić kolor poniżej Androida 21?
Giovanka Bisano

developer.android.com/reference/android/support/v7/widget/… SwitchCompat jest wstecznie kompatybilny z API 7 i nowszym
wingear

1
Jest rok 2020. Naprawdę się zastanawiam, gdzie na świecie ludzie nadal używają Androida 21 i starszych?
zeeshan

18

Rozwiązałem to, aktualizując filtr kolorów, gdy stan przełącznika został zmieniony ...

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

Może być trochę za późno, ale w przypadku przycisków przełącznika przycisk toogle nie jest odpowiedzią, należy zmienić rysowany w parametrze xml przełącznika:

 android:thumb="your drawable here"

9

uczyń możliwym do rysowania „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>

i utwórz plik „newtrack.xml” do rysowania

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

i dodaj go w Switch:

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

1
To działa. Należy jednak zauważyć, że AndroidStudio nie będzie w stanie zasugerować zasobów @drawable dla trackTintlub thumbTint. Trzeba to wpisać ręcznie i działa.
Benjamin Basmaci

Z jakiegoś powodu jest to jedyna odpowiedź, która działa niezawodnie na moim Huawei. Dzięki!
einUsername

7

W systemie Android Lollipop i nowszych wersjach zdefiniuj go w swoim stylu motywu:

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

Problem z tym rozwiązaniem polega na tym, że zmienia ono również kolory moich wybranych tekstów, co nie jest tym, czego chcę.
kodowanie

@codewing Oczywiście, że tak. Ponieważ jest to ustawione w globalnych preferencjach stylu. Aby osiągnąć swój cel, należy znaleźć identyfikator widoku docelowego widoku i zmodyfikować jego atrybuty.
emen

OK, to dotyczy pozycji „Włączone”. A co ze zmianą koloru kciuka w pozycji „Off”?
TavernSenses

7

Stwórz własny obraz z 9 patchami i ustaw go jako tło przycisku przełączania.

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


2
Tak, mógłbym to zrobić, ale na pewno MUSI być łatwiejszy sposób? Może selektory?
JamesSugrue

Nie, nie ma łatwiejszego sposobu. Nie możesz magicznie zmienić koloru obrazu :)
you786

Słuszna uwaga. Nie zrozumiałem w pełni, jak to działa, dopóki nie spojrzałem głębiej.
JamesSugrue

@Denizen, czy na pewno? Jeśli tak, opublikuj odpowiedź, a ja zagłosuję.
you786

@Denizen Usuń swój komentarz. Android Switch zawsze zwraca wartość null dla getBackground (), zmarnowałem 30 minut próbując tego.
Shirish Herwade

5

Rozwiązanie zaproponowane przez arlomedia sprawdziło się u mnie. O jego kwestii ekstraprzestrzeni rozwiązałem usuwając wszystkie wyściółki do przełącznika.

EDYTOWAĆ

Zgodnie z prośbą, oto co mam.

W pliku układu mój przełącznik znajduje się w układzie liniowym i po 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>

Ponieważ pracuję z Xamarin / Monodroid (min. Android 4.1) mój kod to:

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 został wcześniej zdefiniowany w ten sposób (Xamarin):

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

Nie ustawiam wszystkich dopełnień i nie wywołuję .setPadding (0, 0, 0, 0).


Czy możesz podać kod? Próbowałem switchInput.setPadding (0, 0, 0, 0), ale nic się nie zmieniło.
arlomedia

1
Testowane na platformie Xamarin przy użyciu biblioteki AppCompat w celu docelowym w wersji 5.xi działało zgodnie z reklamą.
Alex.Ritna,

4

możesz utworzyć niestandardowy styl dla widgetu przełącznika, który używa akcentu kolorystycznego jako domyślnego, gdy tworzysz dla niego niestandardowy styl

<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

Spróbuj znaleźć właściwą odpowiedź tutaj: Selektor koloru tła TextView . W dwóch słowach powinieneś utworzyć Shape w XML z kolorem, a następnie przypisać go do stanu „zaznaczone” w selektorze.


Niezłe rozwiązanie, ale czy wiesz, jak możemy dynamicznie zmieniać kolor?
inverted_index

Musisz tylko ustawić selektor jako zasób tła
Shamm

1

Nie wiem, jak to zrobić z javy, ale jeśli masz zdefiniowany styl dla swojej aplikacji, możesz dodać tę linię w swoim stylu i będziesz miał dla mnie pożądany kolor, użyłem # 3F51B5

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

1

Najłatwiejszym sposobem jest zdefiniowanie odcienia ścieżki i ustawienie trybu odcienia na src_over, aby usunąć 30% przezroczystości.

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

Jako dodatek do istniejących odpowiedzi: możesz dostosować kciuk i ścieżkę za pomocą selektorów w res/color folderze, na przykład:

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>

Użyj tych selektorów, aby dostosować odcienie ścieżki i kciuka:

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

Należy pamiętać, że jeśli używasz standart Switchi androidnazw dla tych atrybutów, to będzie działać tylko do API 23 i później, więc użytku SwitchCompatz appnazw xmlns:app="http://schemas.android.com/apk/res-auto"jako uniwersalnego rozwiązania.

Wynik:

wprowadź opis obrazu tutaj


0

W xml możesz zmienić kolor jako:

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

Dynamicznie możesz zmieniać jako:

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

-1

Rozwiązanie dla Android Studio 3.6:

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

Zmienia kolor tekstu a w wartości zdefiniowanej w pliku koloru XML (yourColor).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.