190

I'm using a standard Switch control with the holo.light theme in a ICS app.

I want to change the highlighted or on state color of the Toggle Button from the standard light blue to green.

This should be easy, but I can't seem to work out how to do it.

you786
  • 3,735
  • 4
  • 42
  • 67
JamesSugrue
  • 14,401
  • 9
  • 61
  • 93
  • I don't really see any other way than copying the relevant platform resources (selector and *.png files) and modify the 'on' state drawable. Don't forget to point the `Switch` to this custom selector afterwards. – MH. Jun 28 '12 at 23:33
  • 1
    **2021** for anyone googling this very old question, it is now very easy, answer of @مهند عطية below https://stackoverflow.com/a/58362379/294884 – Fattie Apr 02 '21 at 14:23

23 Answers23

300

Late to party but this is how I did

Style

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

Colors

enter image description here

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

Result

See change of colors for enables and disabled switch

enter image description here

Hitesh Sahu
  • 31,496
  • 11
  • 150
  • 116
  • 15
    @MaksimKniazev You have to use `SwitchCompat` ;) – Ovi Trif Apr 04 '18 at 09:17
  • 1
    Good, except of colorControlActivated - it doesn't set track color, only thumb color. – Pointer Null Apr 06 '18 at 11:10
  • 1
    here is solution for Switch and SwitchCompat: https://stackoverflow.com/a/47036089/5869630 – roghayeh hosseini Aug 27 '18 at 19:17
  • – Bay Apr 20 '19 at 19:09
  • @OviTrif Awesome! It is impressive how hard it is to find a simple information like that. Lots and lots of answers I've been reading, and nobody, gave a working answer until now. Finally! – jairhumberto May 29 '20 at 02:13
114

As of now it is better to use SwitchCompat from the AppCompat.v7 library. You can then use simple styling to change the color of your components.

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: Android Developers Blog

EDIT:

The way in which it should be correctly applied is through android:theme="@style/Theme.MyTheme" and also this can be applied to parent styles such as EditTexts, RadioButtons, Switches, CheckBoxes and ProgressBars:

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

<style name="My.Widget.Checkbox" parent="Widget.AppCompat.CompoundButton.CheckBox">
Carlos Daniel
  • 1,572
  • 17
  • 21
SubChord
  • 1,314
  • 1
  • 9
  • 12
  • 1
    Although not applicable at the time, this should be the accepted answer! – Andrew Gallasch Jan 18 '15 at 22:05
  • Have changed this to the accepted answer, as it seems the more "modern" approach to this question. – JamesSugrue Mar 10 '15 at 18:42
  • 1
    I tried all of these and none of them changed the color of the "on" state for my switch. – Adam Johns Apr 04 '15 at 07:33
  • 39
    'on' is `colorAccent`, 'off' is `colorSwitchThumbNormal`. If using the `AppCompat` theme, you need to use `SwitchCompat` rather than `Switch`. If using SDK 23+, you can use `android:thumbTint` and `android:thumbTintMode` with a `ColorStateList`. – Tom Jan 18 '16 at 01:53
  • 2
    @Tom plz reply will those 'android:thumbTint' things will work on devices < 23 – Shirish Herwade Feb 25 '16 at 06:33
  • Would anyone suspect this not to work when my app's base them includes a "colorAccent" field with a different value? I am trying to make an active switch (with "colorAccent") blue when the base theme "colorAccent" is pink. It looks like I am unable to "overwrite" the pink color from the base theme, which is not what I would expect. – ThePartyTurtle Jan 25 '18 at 16:38
  • Note that this didn't won't work for me when I had SwitchCompat instead of switch. Took me a while to figure it out. hopefully it helps someone else. – satyajit Nov 06 '20 at 17:37
51

This is working for me (requires 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);

Note that the "default" state needs to be added last as shown here.

The only problem I see is that the "thumb" of the switch now appears larger than the background or "track" of the switch. I think that's because I'm still using the default track image, which has some empty space around it. However, when I attempted to customize the track image using this technique, my switch appeared to have a height of 1 pixel with just a sliver of the on/off text appearing. There must be a solution for that, but I haven't found it yet...

Update for Android 5

In Android 5, the code above makes the switch disappear completely. We should be able to use the new setButtonTintList method, but this seems to be ignored for switches. But this works:

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

Update for Android 6-7

As Cheruby stated in the comments, we can use the new setThumbTintList and that worked as expected for me. We can also use setTrackTintList, but that applies the color as a blend, with a result that's darker than expected in dark color themes and lighter than expected in light color themes, sometimes to the point of being invisible. In Android 7, I was able to minimize that change that by overriding the track tint mode, but I couldn't get decent results from that in Android 6. You might need to define extra colors that compensate for the blending. (Do you ever get the feeling that Google doesn't want us to customize the appearance of our apps?)

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);
}
arlomedia
  • 7,625
  • 5
  • 53
  • 96
  • I'm using the getThumbDrawable/getTrackDrawable approach to create a switch where both states have the same color - in other words, the switch doesn't enable/disable something, but is used for a choice between two alternatives. – Natix Sep 05 '15 at 22:02
  • 4
    Got that DrawableCompat.setTintList will allow it to work on previous devices. I call: DrawableCompat.setTintList(switchCompat.getThumbDrawable(), foregroundState); – Alexey Oct 20 '16 at 11:25
  • Please edit the answer to include the DrawableCompat solution. It works perfectly! – Dmytro Karataiev Nov 01 '16 at 17:52
  • API 23+: `switchInput.setThumbTintList(buttonStates);` works for Nougat as well. API 21-22: Use the DrawableCompat as suggested by @Alexey. The `switchInput.setButtonTintList(buttonStates);` didn't work for me, it didn't color the states for my Switch. API below 21: `switchInput.getThumbDrawable().setColorFilter(someColor, PorterDuff.Mode.SrcIn);` These worked for me. I worked with Xamarin as well, so translate those to C# in the Android renderers if you use Xamarin.Forms. – Tiffany Dec 20 '16 at 18:56
45

To change Switch style without using style.xml or Java code, you can customize switch into layout XML :

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

It's attribute android:thumbTint and android:trackTint that allowed you to customize color

This is the visual result for this XML :

enter image description here

Kevin ABRIOUX
  • 12,949
  • 7
  • 80
  • 78
37

Create a custom Switch and override setChecked to change color:

  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();
            }
        }
    }
}
Hibbem
  • 1,317
  • 13
  • 20
francisco_ssb
  • 2,847
  • 1
  • 15
  • 22
  • 3
    The first post that actually helped me achieved custom color for the Material Switch without using style or themes. Thanks ! – Mackovich Aug 04 '16 at 14:20
  • 1
    Nice. I already had my own customized Switch, so I've only had to override the setChecked method and all of them automatically changed their colors. Thanks from Spain. – Julio Dec 15 '17 at 19:32
  • Genius !!!!!!!!!! – Fattie Apr 02 '21 at 14:36
32
<androidx.appcompat.widget.SwitchCompat
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:thumbTint="@color/white"
                app:trackTint="@drawable/checker_track"/>

And inside 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>
Benjamin Basmaci
  • 1,398
  • 18
  • 33
wingear
  • 751
  • 7
  • 17
  • `thumbTint` only applies on Android API 21 and above. How if i want to change the colour on below Android 21? – Giovanka Bisano Feb 13 '20 at 05:06
  • https://developer.android.com/reference/android/support/v7/widget/SwitchCompat SwitchCompat is backward compatible with API 7 and above – wingear Feb 14 '20 at 08:04
  • 3
    It is 2020. I really wonder where in the world people still using Android 21 and below? – zeeshan Apr 23 '20 at 18:53
29

While answer by SubChord is correct, is doesnt really answer the question of how to set the "on" color without also affecting other widgets. To do this, use a ThemeOverlay in styles.xml:

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

And reference it in your switch:

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

In so doing it will ONLY affect the color of the views you want to apply it to.

Greg Ennis
  • 13,126
  • 1
  • 64
  • 70
  • For some reason, I also had to set "colorControlActivated" to the same value, yet on POC, it was enough to use "colorAccent". How come? – android developer Jan 10 '17 at 15:27
26

As an addition to existing answers: you can customize thumb and track using selectors in res/color folder, for example:

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 these selectors to customize track and thumb tints:

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

Keep in mind that if you use standart Switch and android namespace for these attributes, it will only work for API 23 and later, so use SwitchCompat with app namespace xmlns:app="http://schemas.android.com/apk/res-auto" as universal solution.

Result:

enter image description here

remain4life
  • 741
  • 1
  • 9
  • 10
20

I solved it by updating the Color Filter when the Switch was state was changed...

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);
    }
}
MCR
  • 1,493
  • 3
  • 20
  • 34
16

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

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

and add it in Switch :

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

Also, it's perfectly OK to make only one drawable file ("switchcolors.xml") and use that for both trackTint and thumbTint.

Fattie
  • 30,632
  • 54
  • 336
  • 607
13

May be its a bit late, but for switch buttons, toogle button is not the answer, you must change the drawable in the xml parameter of the switch:

 android:thumb="your drawable here"
Golgorz
  • 131
  • 1
  • 2
8

In Android Lollipop and above, define it in your theme style:

<style name="BaseAppTheme" parent="Material.Theme">
    ...
    <item name="android:colorControlActivated">@color/color_switch</item>
</style>
emen
  • 5,201
  • 10
  • 52
  • 88
  • The problem with this solution is that it also changes the colors of my selected textedits which is not what I want. – codewing May 22 '16 at 08:15
  • @codewing Of course it will. Because this is set in global style preference. In order to achieve your goal, is to find the view id of your target view and modify its attributes. – emen May 22 '16 at 12:51
  • OK, that's for the "On" position. What about changing the thumb color for the "Off" position? – TavernSenses Jun 21 '18 at 14:12
7

Create your own 9-patch image and set it as the background of the toggle button.

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

codewing
  • 586
  • 5
  • 21
you786
  • 3,735
  • 4
  • 42
  • 67
5

The solution suggested from arlomedia worked for me. About his issue of extraspace I solved removing all the paddings to the switch.

EDIT

As requested, here what I have.

In the layout file, my switch is inside a linear layout and after a 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>

Since I'm working with Xamarin / Monodroid (min. Android 4.1) my code is:

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 is previously defined like this (Xamarin):

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

I don't set at all the paddings and I don't call .setPadding(0, 0, 0, 0).

Daniele D.
  • 2,416
  • 3
  • 34
  • 42
5

Easiest way is defining track tint, and setting tint mode to src_over to remove 30% transparency.

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>
Ege Kuzubasioglu
  • 5,000
  • 10
  • 38
  • 76
4

you can make custom style for switch widget that use color accent as a default when do custom style for it

<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>    
yousef
  • 935
  • 1
  • 10
  • 18
3

You can try this lib, easy to change color for the switch button.
https://github.com/kyleduo/SwitchButton enter image description here

Mike Yang
  • 1,864
  • 1
  • 19
  • 25
3

This worked for me -:

1.code in values/styles.xml -:

 <style name="SwitchTheme" parent="Theme.AppCompat.Light">
    <item name="android:colorControlActivated">#148E13</item>
</style>

2.add following line of code in your switch in your layout file -:

android:theme="@style/SwitchTheme"
1

Try to find out right answer here: Selector on background color of TextView. In two words you should create Shape in XML with color and then assign it to state "checked" in your selector.

Community
  • 1
  • 1
Shamm
  • 924
  • 6
  • 9
1

I dont know how to do it from java , But if you have a style defined for your app you can add this line in your style and you will have the desired color for me i have used #3F51B5

<color name="ascentColor">#3F51B5</color>
erluxman
  • 13,712
  • 15
  • 67
  • 99
0

In xml , you can change the color as :

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

Dynamically you can change as :

Switch.thumbDrawable.setColorFilter(ContextCompat.getColor(requireActivity(), R.color.darkBlue), PorterDuff.Mode.MULTIPLY)
ROHIT LIEN
  • 419
  • 3
  • 8
0

Based on a combination of a few of the answers here this is what worked for me.

<Switch
    android:trackTintMode="src_over"
    android:thumbTint="@color/white"
    android:trackTint="@color/shadow"
    android:checked="true"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
Francislainy Campos
  • 1,743
  • 11
  • 36
-2

Solution for Android Studio 3.6:

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

Changes the text color of a in the color XML file defined value (yourColor).

ChristianYami
  • 652
  • 1
  • 7
  • 14