How to change the track color of a SwitchCompat

AndroidColorsSwitchcompat

Android Problem Overview


I've tried using the following link to change the color of a SwitchCompat:

https://stackoverflow.com/questions/26714864/how-to-change-the-color-of-a-switchcompat

Notice the low constrast in my switch:

The SwitchCompat

But after changing all relevant color values the track (the brighter grey) of the SwitchCompat remains the same. I don't want to change the appearance except the color. The thumb is in pink, and I want the track to have some contrast. Did I miss to define a value in my styles.xml?

I tried these values (random non-white colors):

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/first</item>
    <item name="colorPrimaryDark">@color/second</item>
    <item name="colorAccent">@color/third</item>
   ...
    <item name="colorControlActivated">@color/first</item>
    <item name="colorControlHighlight">@color/first</item>
    <item name="colorControlNormal">@color/second</item>
    <item name="colorSwitchThumbNormal">@color/second</item>
    <item name="colorButtonNormal">@color/second</item>
...>

Android Solutions


Solution 1 - Android

I had same probrem and solved it.

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
   ...
   <!-- Active thumb color & Active track color(30% transparency) -->
   <item name="colorControlActivated">@color/theme</item>
   <!-- Inactive thumb color -->
   <item name="colorSwitchThumbNormal">@color/grey300</item>
   <!-- Inactive track color(30% transparency) -->
   <item name="android:colorForeground">@color/grey600</item>
   ...
</style>

I read app compat code, and understand it.

android.support.v7.internal.widget.TintManager.java

private ColorStateList getSwitchTrackColorStateList() {
    if (mSwitchTrackStateList == null) {
        final int[][] states = new int[3][];
        final int[] colors = new int[3];
        int i = 0;

        // Disabled state
        states[i] = new int[] { -android.R.attr.state_enabled };
        colors[i] = getThemeAttrColor(android.R.attr.colorForeground, 0.1f);
        i++;

        states[i] = new int[] { android.R.attr.state_checked };
        colors[i] = getThemeAttrColor(R.attr.colorControlActivated, 0.3f);
        i++;

        // Default enabled state
        states[i] = new int[0];
        colors[i] = getThemeAttrColor(android.R.attr.colorForeground, 0.3f);
        i++;

        mSwitchTrackStateList = new ColorStateList(states, colors);
    }
    return mSwitchTrackStateList;
}

Solution 2 - Android

Below is the AppCompat way of changing both the track and thumb color programmatically, for a specific SwitchCompat. For this example, I have hardcoded the thumbColor to red. Ideally, you would set the color through a second method parameter.

Please note that when the switch is checked, a ripple is displayed. The ripple color will not be changed by the code below.

public static void setSwitchColor(SwitchCompat v) {
    // thumb color of your choice
    int thumbColor = Color.RED;

    // trackColor is the thumbColor with 30% transparency (77)
    int trackColor = Color.argb(77, Color.red(thumbColor), Color.green(thumbColor), Color.blue(thumbColor));

    // setting the thumb color
    DrawableCompat.setTintList(v.getThumbDrawable(), new ColorStateList(
            new int[][]{
                    new int[]{android.R.attr.state_checked},
                    new int[]{}
            },
            new int[]{
                    thumbColor,
                    Color.WHITE
            }));

    // setting the track color
    DrawableCompat.setTintList(v.getTrackDrawable(), new ColorStateList(
            new int[][]{
                    new int[]{android.R.attr.state_checked},
                    new int[]{}
            },
            new int[]{
                    trackColor,
                    Color.parseColor("#4D000000") // full black with 30% transparency (4D)
            }));
}

Solution 3 - Android

if you want to costumize the color of track.you can use this solution.

> track selector.xml

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

where checked_color and unchecked_color are color of your choices.

> styles.xml

<style name="mySwitchStyle" parent="@style/Widget.AppCompat.CompoundButton.Switch">
       <!-- do here for additional costumization on thumb, track background,text appearance -->
        

    </style>


<style name="mySwitchTheme" parent="ThemeOverlay.AppCompat.Light">
        <item name="switchStyle">@style/mySwitchStyle</item>
        <item name="colorControlActivated">@color/red</item>
        <item name="colorControlNormal">@color/colorAccent</item>
        <item name="trackTint">@color/track_selector</item>
    </style>

> layout file

<android.support.v7.widget.SwitchCompat
        android:theme="@style/mySwitchTheme"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

Solution 4 - Android

With the MaterialSwitch provided by the Material Components Library.

  • Use the materialThemeOverlay attribute to override the app color for the Switch.

  <style name="CustomWidget.MaterialComponents.CompoundButton.Switch" parent="Widget.MaterialComponents.CompoundButton.Switch">
    <item name="materialThemeOverlay">@style/CustomCompoundButton_Switch</item>
  </style>
  <style name="CustomCompoundButton_Switch" >
    <item name="colorSurface">@color/yellow</item>
    <item name="colorOnSurface">@color/orange</item>
    <item name="colorControlActivated">@color/blue</item>
  </style>

And in the layout:

<com.google.android.material.switchmaterial.SwitchMaterial
    style="@style/Widget.MaterialComponents.CompoundButton.Switch"
    ../>

enter image description hereenter image description here

  • Use the style attribute:

  <style name="CustomStyleWidget.MaterialComponents.CompoundButton.Switch"
         parent="Widget.MaterialComponents.CompoundButton.Switch">
    <item name="useMaterialThemeColors">false</item>
    <item name="trackTint">@color/track_selector</item>
    <item name="thumbTint">@color/thumb_selector</item>
  </style>

with thumb_selector:

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

and track_selector:

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

And in the layout:

<com.google.android.material.switchmaterial.SwitchMaterial
    style="@style/CustomStyleWidget.MaterialComponents.CompoundButton.Switch"
    ../>

Solution 5 - Android

If you want a more switches in multiple colors in one Activity, you can use this solution (based on theme by @Konifar):

<style name="CustomSwitchTheme" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    <!-- Active thumb color & Active track color(30% transparency) -->
    <item name="colorControlActivated">@color/custom</item>
    <!-- Inactive thumb color -->
    <item name="colorSwitchThumbNormal">#E0E0E0</item>
    <!-- Inactive track color(30% transparency) -->
    <item name="android:colorForeground">#757575</item>
</style>

where @color/custom is color of thumb when switch is activated.

Then apply this theme to your SwitchCompat this way:

<android.support.v7.widget.SwitchCompat
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:theme="@style/CustomSwitchTheme" />

Solution 6 - Android

 Here is Switch Layout
 -Adding theme to your switch to change the color of track.Check the style given below:-.

**Switch Compact**
  <android.support.v7.widget.SwitchCompat
                android:id="@+id/goOnlineBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:theme="@style/Switch_style/>


**Switch_style**
   <style name="Switch_style" parent="Theme.AppCompat.Light">
        <!-- active thumb & track color (30% transparency) -->
        <item name="colorControlNormal">@android:color/white</item>
        <item name="colorControlActivated">@android:color/blue</item>
        <item name="colorSwitchThumbNormal">@android:color/white</item>
        <item name="trackTint">@color/white</item>
   </style>

Where trackTint will change your track color

Solution 7 - Android

Here is how a developer can change the track drawable of a SwitchCompat:
First, in the root layout, write xmlns:SwitchCompat="http://schemas.android.com/apk/res-auto"
Then:

    <android.support.v7.widget.SwitchCompat
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:thumb="@drawable/your_switch_thumb"
        SwitchCompat:track="@drawable/your_switch_track_selector" 
        />

where your_switch_track_selector can be:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/switch_ios_track_on" android:state_checked="true" />
    <item android:drawable="@drawable/switch_ios_track_off" android:state_checked="false" />
</selector>

1.switch_ios_track_on:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <solid android:color="#4EDA62" />
    <corners android:radius="20dp" />
</shape>

2.switch_ios_track_off:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <solid android:color="#E3E3E3" />
    <corners android:radius="20dp" />
</shape>

Simple and easy..

Solution 8 - Android

I was having the same problem. Finally solved it programatically with this Kotlin code

fun tintSwitchButton(sw: SwitchCompat, resolvedColor: Int) {
    val states = arrayOf(
            intArrayOf(-android.R.attr.state_pressed),
            intArrayOf(android.R.attr.state_pressed)
    )

    DrawableCompat.setTintList(sw?.trackDrawable, ColorStateList(
            states,
            intArrayOf(resolvedColor, resolvedColor)
    ))

    DrawableCompat.setTintList(sw?.thumbDrawable, ColorStateList(
            states,
            intArrayOf(Color.WHITE, Color.WHITE)
    ))
}

And the function call is

tintSwitchButton(switchCompat, Color.rgb(214, 0, 0))

You can also create an extension function:

fun SwitchCompat.tint(resolvedColor: Int) {
    val states = arrayOf(
        intArrayOf(-android.R.attr.state_pressed),
        intArrayOf(android.R.attr.state_pressed)
    )

    DrawableCompat.setTintList(trackDrawable, ColorStateList(
        states,
        intArrayOf(resolvedColor, resolvedColor)
    ))

    DrawableCompat.setTintList(thumbDrawable, ColorStateList(
        states,
        intArrayOf(Color.WHITE, Color.WHITE)
    ))
}

So the call would be easier

switchCompat.tint(Color.rgb(214,0,0))

Solution 9 - Android

just use colorControlActivated to set the color of SwitchCompat's track and thumb.

If not set, the default colorControlActivated color will use colorAccent. (from the experience, still not find where in the source code).

The source code changed and does not still like @Ovidiu said. But still thanks him for let me know to find the answer from the source code.

mThumbDrawable = a.getDrawable(R.styleable.SwitchCompat_android_thumb);

will eventually call the following method.

/frameworks/support/v7/appcompat/src/android/support/v7/widget/AppCompatDrawableManager.java

private ColorStateList createSwitchTrackColorStateList(Context context) {
    final int[][] states = new int[3][];
    final int[] colors = new int[3];
    int i = 0;

    // Disabled state
    states[i] = ThemeUtils.DISABLED_STATE_SET;
    colors[i] = getThemeAttrColor(context, android.R.attr.colorForeground, 0.1f);
    i++;

    states[i] = ThemeUtils.CHECKED_STATE_SET;
    colors[i] = getThemeAttrColor(context, R.attr.colorControlActivated, 0.3f);
    i++;

    // Default enabled state
    states[i] = ThemeUtils.EMPTY_STATE_SET;
    colors[i] = getThemeAttrColor(context, android.R.attr.colorForeground, 0.3f);
    i++;

    return new ColorStateList(states, colors);
}

private ColorStateList createSwitchThumbColorStateList(Context context) {
    final int[][] states = new int[3][];
    final int[] colors = new int[3];
    int i = 0;

    final ColorStateList thumbColor = getThemeAttrColorStateList(context,
            R.attr.colorSwitchThumbNormal);

    if (thumbColor != null && thumbColor.isStateful()) {
        // If colorSwitchThumbNormal is a valid ColorStateList, extract the default and
        // disabled colors from it

        // Disabled state
        states[i] = ThemeUtils.DISABLED_STATE_SET;
        colors[i] = thumbColor.getColorForState(states[i], 0);
        i++;

        states[i] = ThemeUtils.CHECKED_STATE_SET;
        colors[i] = getThemeAttrColor(context, R.attr.colorControlActivated);
        i++;

        // Default enabled state
        states[i] = ThemeUtils.EMPTY_STATE_SET;
        colors[i] = thumbColor.getDefaultColor();
        i++;
    } else {
        // Else we'll use an approximation using the default disabled alpha

        // Disabled state
        states[i] = ThemeUtils.DISABLED_STATE_SET;
        colors[i] = getDisabledThemeAttrColor(context, R.attr.colorSwitchThumbNormal);
        i++;

        states[i] = ThemeUtils.CHECKED_STATE_SET;
        colors[i] = getThemeAttrColor(context, R.attr.colorControlActivated);
        i++;

        // Default enabled state
        states[i] = ThemeUtils.EMPTY_STATE_SET;
        colors[i] = getThemeAttrColor(context, R.attr.colorSwitchThumbNormal);
        i++;
    }

    return new ColorStateList(states, colors);
}

Solution 10 - Android

SwitchCompat is a Material Design widget. when my activity extends AppCompatActivity and android:theme="@style/mySwitch" is worked.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionClose CallView Question on Stackoverflow
Solution 1 - AndroidKonifarView Answer on Stackoverflow
Solution 2 - AndroidOvidiuView Answer on Stackoverflow
Solution 3 - AndroidAnjul khanalView Answer on Stackoverflow
Solution 4 - AndroidGabriele MariottiView Answer on Stackoverflow
Solution 5 - AndroidLukas NovakView Answer on Stackoverflow
Solution 6 - AndroidRajView Answer on Stackoverflow
Solution 7 - AndroidKnIfERView Answer on Stackoverflow
Solution 8 - AndroidvoghDevView Answer on Stackoverflow
Solution 9 - AndroidFrancis BaconView Answer on Stackoverflow
Solution 10 - AndroidXiaoJianView Answer on Stackoverflow