Search code examples
androidswitchcompat

How to change the color of a SwitchCompat from AppCompat library


I have a few switch controls with different colors in my application and to change their colors I used multiple custom drawable selectors.

A new android.support.v7.widget.SwitchCompat control was introduced with the release of the AppCompat v21 library.

Is it possible to change the color of a SwitchCompat programmatically without customer drawable selector, but with XML or code?


Solution

  • AppCompat tinting attributs:

    First, you should take a look to appCompat lib article there and to different attributs you can set:

    colorPrimary: The primary branding color for the app. By default, this is the color applied to the action bar background.

    colorPrimaryDark: Dark variant of the primary branding color. By default, this is the color applied to the status bar (via statusBarColor) and navigation bar (via navigationBarColor).

    colorAccent: Bright complement to the primary branding color. By default, this is the color applied to framework controls (via colorControlActivated).

    colorControlNormal: The color applied to framework controls in their normal state.

    colorControlActivated: The color applied to framework controls in their activated (ex. checked, switch on) state.

    colorControlHighlight: The color applied to framework control highlights (ex. ripples, list selectors).

    colorButtonNormal: The color applied to framework buttons in their normal state.

    colorSwitchThumbNormal: The color applied to framework switch thumbs in their normal state. (switch off)


    If all custom switches are the same in a single activity:

    With previous attributes you can define your own theme for each activity:

    <style name="Theme.MyActivityTheme" 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>
    

    and :

    <manifest>
    ...
        <activity
            android:name=".MainActivity" 
            android:theme="@style/Theme.MyActivityTheme">
        </activity>
    ...
    </manifest>
    

    If you want to have differents custom switches in a single activity:

    As widget tinting in appcompat works by intercepting any layout inflation and inserting a special tint-aware version of the widget in its place (See Chris Banes post about it) you can not apply a custom style to each switch of your layout xml file. You have to set a custom Context that will tint switch with right colors.

    --

    To do so for pre-5.0 you need to create a Context that overlays global theme with customs attributs and then create your switches programmatically:

    ContextThemeWrapper ctw = ContextThemeWrapper(getActivity(), R.style.Color1SwitchStyle); 
    SwitchCompat sc = new SwitchCompat(ctw)
    

    As of AppCompat v22.1 you can use the following XML to apply a theme to the switch widget:

    <RelativeLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        ...>
    
        <android.support.v7.widget.SwitchCompat
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:theme="@style/Color1SwitchStyle"/>
    

    Your custom switch theme:

    <style name="Color1SwitchStyle">
        <item name="colorControlActivated">@color/my_awesome_color</item>
    </style>
    

    --

    On Android 5.0 it looks like a new view attribut comes to life : android:theme (same as one use for activity declaration in manifest). Based on another Chris Banes post, with the latter you should be able to define a custom theme directly on a view from your layout xml:

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

    To change the track color of a SwitchCompat

    Thanks to vine'th I complete my answer with a link to SO answer that explains how to specify the Foreground of the Track when Switch is Off, it's there.