Change “on” color of a Switch

守給你的承諾、 提交于 2019-12-17 02:42:12

问题


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.


回答1:


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



回答2:


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

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




回答3:


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



回答4:


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 :




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



回答6:


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.




回答7:


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



回答8:


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"



回答9:


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



回答10:


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>



回答11:


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/




回答12:


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




回答13:


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



回答14:


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>    



回答15:


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




回答16:


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.




回答17:


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>


来源:https://stackoverflow.com/questions/11253512/change-on-color-of-a-switch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!