更改开关的“打开”颜色


156

我在ICS应用程序中使用带有holo.light主题的标准Switch控件。

我想将“切换按钮”的突出显示或开启状态颜色从标准的浅蓝色更改为绿色。

这应该很容易,但是我似乎无法解决该怎么做。


除了复制相关平台资源(选择器和* .png文件)并修改“ on”状态可绘制对象外,我没有其他方法。之后不要忘记将指向Switch此自定义选择器。
MH。

Answers:


99

到目前为止,最好使用AppCompat.v7库中的SwitchCompat。然后,您可以使用简单的样式来更改组件的颜色。

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>

参考:Android开发者博客

编辑

正确应用该方法的方式是通过android:theme="@style/Theme.MyTheme" ,也可以将其应用于父样式,例如EditTexts,RadioButtons,Switches,CheckBoxes和ProgressBars:

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

<style name="My.Widget.Checkbox" parent="Widget.AppCompat.CompoundButton.CheckBox">

1
尽管当时不适用,但这应该是公认的答案!
Andrew Gallasch 2015年

已将其更改为已接受的答案,因为对于此问题似乎是更“现代”的方法。
JamesSugrue

1
我尝试了所有这些,但没有一个改变我的开关的“ on”状态的颜色。
亚当·约翰斯

31
“开”是colorAccent,“关”是colorSwitchThumbNormal。如果使用AppCompat主题,则需要使用SwitchCompat而不是Switch。如果使用SDK 23+,则可以将android:thumbTintandroid:thumbTintMode与一起使用ColorStateList
汤姆

1
@Tom plz回复那些“ android:thumbTint”的东西将在<23的设备上运行
Shirish Herwade

269

派对晚了,但这就是我的做法

样式

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

色彩

在此处输入图片说明

布局

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

结果

查看启用和禁用开关的颜色变化

在此处输入图片说明


14
@MaksimKniazev,您必须使用SwitchCompat;)
Ovi Trif

1
很好,除了colorControlActivated-它不设置轨道颜色,仅设置拇指颜色。
指针为空,2018年

1
这是Switch和SwitchCompat的解决方案:stackoverflow.com/a/47036089/5869630
roghayeh hosseini

<style>标签需要写在res >> values >> styles.xml和<Switch ...>的XML页面上,您只应添加以下行:android:theme =“ @ style / SCBSwitch,我的颜色是:colorControlActivated“>#ff0000和colorSwitchThumbNormal”>#00ff00和android:colorForeground“>#00ff00

@OviTrif太棒了!找到这样的简单信息非常困难,这令人印象深刻。我一直在阅读很多答案,但到目前为止,还没有人给出有效的答案。最后!
jairhumberto

49

这对我有用(需要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);

请注意,“默认”状态需要最后添加,如下所示。

我看到的唯一问题是,开关的“拇指”现在看起来大于开关的背景或“轨道”。我认为这是因为我仍在使用默认的轨迹图像,它周围有一些空白空间。但是,当我尝试使用此技术自定义轨道图像时,我的开关似乎具有1像素的高度,只出现了少量开/关文本。一定有解决方案,但是我还没有找到……

Android 5更新

在Android 5中,上面的代码使开关完全消失。我们应该能够使用新的 setButtonTintList方法,但是对于开关来说,这似乎被忽略了。但这有效:

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

Android 6-7更新

正如Cheruby在评论中指出的那样,我们可以使用新的setThumbTintList和对我有用的产品。我们也可以使用setTrackTintList,但是将颜色混合使用,结果比深色主题中的预期要暗,比浅色主题中的预期要亮,有时甚至不可见。在Android 7中,我可以通过覆盖跟踪色调模式来最小化该更改,但是在Android 6中,我无法获得令人满意的结果。您可能需要定义其他颜色来补偿混合。(您是否曾经有过Google不想让我们自定义应用外观的感觉?)

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

我正在使用getThumbDrawable / getTrackDrawable方法创建一个开关,其中两个状态都具有相同的颜色-换句话说,该开关不启用/禁用某些功能,而是用于在两种选择之间进行选择。
Natix

4
得到了DrawableCompat.setTintList将允许它在以前的设备上工作。我称呼为:DrawableCompat.setTintList(switchCompat.getThumbDrawable(),foregroundState);
Alexey

请编辑答案以包括DrawableCompat解决方案。它完美地工作!
Dmytro Karataiev

API 23+:也switchInput.setThumbTintList(buttonStates); 适用于牛轧糖。API 21-22:按照@Alexey的建议使用DrawableCompat。那个switchInput.setButtonTintList(buttonStates);对我没有用,它没有为我的Switch着色状态。低于21的API: switchInput.getThumbDrawable().setColorFilter(someColor, PorterDuff.Mode.SrcIn); 这些对我有用。我也使用Xamarin,因此,如果您使用Xamarin.Forms,请在Android渲染器中将其转换为C#。
Cheruby

37

要在不使用style.xml或Java代码的情况下更改Switch样式,可以将switch自定义为布局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" />

它是android:thumbTintandroid:trackTint的属性,可让您自定义颜色

这是此XML的视觉结果:

在此处输入图片说明


17
无论拇指是打开还是关闭,这都会改变拇指的颜色。
Android开发人员

1
“属性thumbTint仅在API级别21和更高版本中使用”
norbDEV

6
@norbDEV通过AppCompat.v7库中的SwitchCompat使用app:thumbTint和app:trackTint获得较低的API级别。
戴维·达里亚斯

那行得通,但是如果您想根据打开或关闭的方式更改拇指的颜色怎么办?
TavernSenses

2
如果你想使用thumbTint低于21的使用app:thumbTint,而不是android:thumbTint和变化switchSwitchCompat
Kavita_p

33

创建一个自定义的Switch并覆盖setChecked以更改颜色:

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

2
实际上帮助我在不使用样式或主题的情况下为Material Switch实现了自定义颜色的第一篇文章。谢谢 !
Mackovich

1
真好 我已经有了自己的自定义开关,因此只需要重写setChecked方法,它们都将自动更改其颜色。感谢西班牙。
Julio

22

虽然SubChord的回答是正确的,但并不能真正回答如何设置“ on”颜色而不影响其他小部件的问题。为此,请ThemeOverlay在styles.xml中使用:

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

并在您的开关中引用它:

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

这样做只会影响您要应用它的视图的颜色。


由于某些原因,我还必须将“ c​​olorControlActivated”设置为相同的值,但是在POC上,使用“ colorAccent”就足够了。怎么会?
Android开发人员

22
<androidx.appcompat.widget.SwitchCompat
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:thumbTint="@color/white"
                app:trackTint="@drawable/checker_track"/>

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

thumbTint仅适用于Android API 21及更高版本。我要如何在Android 21以下更改颜色?
Giovanka Bisano


1
现在是2020年。我真的很想知道世界上还有哪些人在使用Android 21及更低版本?
zeeshan

18

当开关状态更改时,我通过更新滤色器解决了该问题。

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

13

可能有点晚了,但是对于开关按钮,toogle按钮不是答案,您必须在开关的xml参数中更改drawable:

 android:thumb="your drawable here"

9

使可绘制“ 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>

并使可绘制的“ 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>

并将其添加到Switch中:

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

1
这可行。但是,应注意,AndroidStudio无法为trackTint或建议@drawable资源thumbTint。一个人需要手动编写它,然后它才能工作。
本杰明·巴斯马奇

由于某种原因,这是唯一可以在我的华为上可靠工作的答案。谢谢!
einUsername

7

在Android Lollipop及更高版本中,以您的主题样式定义它:

<style name="BaseAppTheme" parent="Material.Theme">
    ...
    <item name="android:colorControlActivated">@color/color_switch</item>
</style>

该解决方案的问题在于,它还会更改我选择的textedit的颜色,这不是我想要的颜色。
codewing

@codewing当然会。因为这是在全局样式首选项中设置的。为了实现您的目标,就是找到目标视图的视图ID并修改其属性。
emen

好的,那是“开”的位置。如何更改“关”位置的拇指颜色?
TavernSenses

7

创建自己的9色块图像并将其设置为切换按钮的背景。

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


2
是的,可以这样做,但是肯定有一种更简单的方法吗?选择器也许?
JamesSugrue 2012年

不,没有更简单的方法。您无法神奇地更改图像的颜色:)
you786 2012年

好点子。在深入了解之前,我还没有完全了解它是如何工作的。
JamesSugrue 2012年

@Denizen,您确定吗?如果是这样,请发布答案,我会投票赞成。
you786

@Denizen请删除您的评论。Android Switch始终为getBackground()返回null,我为此浪费了30分钟。
Shirish Herwade '16

5

arlomedia建议的解决方案对我有用。关于他的多余空间问题,我解决了删除交换机的所有填充的问题。

编辑

根据要求,这里是我所拥有的。

在布局文件中,我的开关位于线性布局内,并且位于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>

由于我正在使用Xamarin / Monodroid(最低Android 4.1),因此我的代码是:

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以前是这样定义的(Xamarin):

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

我没有设置所有填充,也没有调用.setPadding(0,0,0,0)。


您可以为此提供代码吗?我尝试了switchInput.setPadding(0,0,0,0)但没有任何变化。
arlomedia

1
使用AppCompat库以5.x为目标,在Xamarin中进行了测试,此功能与广告中所述的相同。
Alex.Ritna 2015年

4

您可以为自定义样式的开关小部件创建自定义样式,在为其自定义样式时使用默认颜色

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


1

尝试在此处找出正确的答案:TextView背景色的选择器。用两个词用XML创建带有颜色的Shape,然后在选择器中将其分配为状态“ checked”。


好的解决方案,但是您知道我们如何动态更改颜色吗?
反转

您只需要将选择器设置为背景资源
Shamm

1

我不知道如何从java做到这一点,但是如果您为应用定义了样式,则可以在样式中添加此行,并且您将获得所需的颜色,我已经使用#3F51B5

<color name="ascentColor">#3F51B5</color>

1

最简单的方法是定义轨道色调,并将色调模式设置为src_over以删除30%的透明度。

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>

0

作为现有答案的补充:您可以使用以下选项中的选择器来自定义拇指和轨迹 res/color文件夹中的,例如:

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>

使用以下选择器来自定义轨迹和拇指色调:

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

请记住,如果对这些属性使用standart Switchandroid名称空间,则它仅适用于API 23及更高版本,因此请SwitchCompatapp名称空间配合使用xmlns:app="http://schemas.android.com/apk/res-auto"作为通用的解决方案。

结果:

在此处输入图片说明


0

在xml中,您可以将颜色更改为:

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

您可以动态更改为:

Switch.thumbDrawable.setColorFilter(ContextCompat.getColor(requireActivity(), R.color.darkBlue), PorterDuff.Mode.MULTIPLY)

-1

Android Studio 3.6解决方案:

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

更改颜色XML文件定义值(yourColor)中a的文本颜色。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.