'Change "on" color of a Switch

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.



Solution 1:[1]

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

Solution 2:[2]

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

Solution 3:[3]

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

Solution 4:[4]

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

Solution 5:[5]

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

Solution 6:[6]

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

Solution 7:[7]

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

Use app:trackTint and app:thumbTint instead for switch compat androidx – see @Ehsan Rosdi's comments.

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

Solution 8:[8]

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.

Solution 9:[9]

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

Solution 10:[10]

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"

Solution 11:[11]

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>

Solution 12:[12]

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/

Solution 13:[13]

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"

Solution 14:[14]

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

Solution 15:[15]

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>

Solution 16:[16]

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>    

Solution 17:[17]

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

Solution 18:[18]

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.

Solution 19:[19]

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>

Solution 20:[20]

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)

Solution 21:[21]

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

Solution 22:[22]

Change the tint colour for track and thumb drawable.

switch.getThumbDrawable().setTint(ContextCompat.getColor(this,R.color.colorAccent));

switch.getTrackDrawable().setTint(ContextCompat.getColor(this,R.color.colorAccent));

Solution 23:[23]

Android 2022 - most simple and straightforward method:

change in

/res/values/themes.xml

FROM

<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>

TO

<!-- Secondary brand color. -->
<item name="colorSecondary">@color/purple_500</item>
<item name="colorSecondaryVariant">@color/purple_700</item>

Solution 24:[24]

Programattically if you want to change Switch Component Color use this code below:

    binding.switchCompatBackupMedia.thumbTintList =
                ColorStateList.valueOf(Color.parseColor("#00C4D3"))
            binding.switchCompatBackupMedia.trackTintList =
                ColorStateList.valueOf(Color.parseColor("#00C4D31F"))

Solution 25:[25]

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