【问题标题】:Change "on" color of a Switch更改开关的“开启”颜色
【发布时间】:2012-06-30 11:55:19
【问题描述】:

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

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

这应该很容易,但我似乎不知道该怎么做。

【问题讨论】:

  • 除了复制相关的平台资源(选择器和 *.png 文件)并修改“on”状态可绘制对象之外,我真的没有看到任何其他方法。之后不要忘记将Switch 指向此自定义选择器。
  • 2021 对于任何在谷歌上搜索这个非常古老的问题的人,现在很容易,@مهند عطية 的回答低于stackoverflow.com/a/58362379/294884

标签: android togglebutton


【解决方案1】:

聚会迟到了,但我就是这样做的

风格

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

结果

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

【讨论】:

  • @MaksimKniazev 你必须使用SwitchCompat ;)
  • 好,除了 colorControlActivated - 它不设置轨道颜色,只有拇指颜色。
  • 这里是 Switch 和 SwitchCompat 的解决方案:stackoverflow.com/a/47036089/5869630
  • @OviTrif 太棒了!令人印象深刻的是,要找到这样一个简单的信息是多么困难。我一直在阅读很多很多答案,直到现在没有人给出有效的答案。终于!
【解决方案2】:

到目前为止,最好使用 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 Developers Blog

编辑

正确应用的方式是通过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">

【讨论】:

  • 虽然当时不适用,但这应该是公认的答案!
  • 已将其更改为已接受的答案,因为这似乎是解决这个问题的更“现代”的方法。
  • 我尝试了所有这些方法,但它们都没有改变我的开关“开启”状态的颜色。
  • 'on' 是 colorAccent,'off' 是 colorSwitchThumbNormal。如果使用AppCompat 主题,则需要使用SwitchCompat 而不是Switch。如果使用 SDK 23+,您可以使用 android:thumbTintandroid:thumbTintModeColorStateList
  • @Tom 请回复那些“android:thumbTint”的东西是否可以在设备上运行
【解决方案3】:

这对我有用(需要 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 在 cmets 中所说,我们可以使用新的 setThumbTintList,这对我来说就像预期的那样工作。我们也可以使用setTrackTintList,但这会将颜色作为混合颜色应用,结果在深色主题中比预期的要暗,在浅色主题中比预期的要亮,有时甚至到了不可见的程度。在 Android 7 中,我可以通过覆盖轨道 tint mode 来最小化这种变化,但在 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 方法来创建两个状态具有相同颜色的开关 - 换句话说,该开关不会启用/禁用某些东西,而是用于在两种选择。
  • 知道 DrawableCompat.setTintList 将允许它在以前的设备上工作。我打电话:DrawableCompat.setTintList(switchCompat.getThumbDrawable(), foregroundState);
  • 请编辑答案以包含 DrawableCompat 解决方案。效果很好!
  • API 23+: switchInput.setThumbTintList(buttonStates); 也适用于牛轧糖。 API 21-22:使用 @Alexey 建议的 DrawableCompat。 switchInput.setButtonTintList(buttonStates); 对我不起作用,它没有为我的 Switch 着色。 API 低于 21:switchInput.getThumbDrawable().setColorFilter(someColor, PorterDuff.Mode.SrcIn); 这些对我有用。我也使用 Xamarin,因此如果您使用 Xamarin.Forms,请将它们转换为 Android 渲染器中的 C#。
【解决方案4】:

要在不使用 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 的视觉结果:

【讨论】:

  • 这会改变拇指的颜色,无论它是打开还是关闭。
  • "属性 thumbTint 仅用于 API 级别 21 及更高级别"
  • @norbDEV 将 app:thumbTint 和 app:trackTint 与 AppCompat.v7 库中的 SwitchCompat 结合使用以获得较低的 API 级别。
  • 这行得通,但是如果你想改变拇指的颜色,取决于它是打开还是关闭?
  • 如果你想使用 thumbTint 低于 21 使用 app:thumbTint 而不是 android:thumbTint 并将 switch 更改为 SwitchCompat
【解决方案5】:

作为现有答案的补充:您可以使用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"/>

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

结果:

【讨论】:

    【解决方案6】:

    创建自定义 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();
                }
            }
        }
    }
    

    【讨论】:

    • 第一篇真正帮助我在不使用样式或主题的情况下为 Material Switch 实现自定义颜色的帖子。谢谢!
    • 不错。我已经有了自己定制的 Switch,所以我只需要重写 setChecked 方法,它们都会自动更改颜色。来自西班牙的感谢。
    【解决方案7】:
    <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 以下更改颜色怎么办?
    • developer.android.com/reference/android/support/v7/widget/… SwitchCompat 向后兼容 API 7 及更高版本
    • 现在是 2020 年。我真的想知道世界上还有哪些人还在使用 Android 21 及以下版本?
    【解决方案8】:

    制作可绘制的“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"
             />
    

    此外,只制作一个可绘制文件(“switchcolors.xml”)并将其用于 trackTint 和 thumbTint 也是完全可以的。

    【讨论】:

    • 这行得通。不过需要注意的是,AndroidStudio 将无法为trackTintthumbTint 推荐@drawable 资源。需要手动编写它,它可以工作。
    • 出于某种原因,这是在我的华为上可靠运行的唯一答案。谢谢!
    • 非常感谢
    • 发送了一个赏金!
    • 使用 app:trackTint 和 app:thumbTint 代替 switch compat androidx
    【解决方案9】:

    虽然 SubChord 的回答是正确的,但并没有真正回答如何在不影响其他小部件的情况下设置“开启”颜色的问题。为此,请在styles.xml 中使用ThemeOverlay

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

    并在您的开关中引用它:

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

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

    【讨论】:

    • 出于某种原因,我还必须将“colorControlActivated”设置为相同的值,但在 POC 上,使用“colorAccent”就足够了。怎么会?
    【解决方案10】:

    当 Switch 状态发生变化时,我通过更新滤色器解决了这个问题...

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

    【讨论】:

      【解决方案11】:

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

       android:thumb="your drawable here"
      

      【讨论】:

        【解决方案12】:

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

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

        【讨论】:

        • 这个解决方案的问题是它还会改变我选择的文本编辑器的颜色,这不是我想要的。
        • @codewing 当然会。因为这是在全局样式偏好中设置的。为了达到你的目的,就是找到你的目标视图的视图id并修改它的属性。
        • 好的,这是“开”的位置。更改“关闭”位置的拇指颜色怎么样?
        【解决方案13】:

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

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

        【讨论】:

        • 是的,可以这样做,但肯定有更简单的方法吗?选择器可能吗?
        • 不,没有更简单的方法。你不能神奇地改变图像的颜色:)
        • 好点。在深入了解之前,我并没有完全了解它是如何工作的。
        • @Denizen,你确定吗?如果是这样,请发布答案,我会投票。
        • @Denizen 请删除您的评论。 Android Switch 总是为 getBackground() 返回 null,我浪费了 30 分钟尝试这个。
        【解决方案14】:

        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) 但没有任何改变。
        • 在 Xamarin 中使用 AppCompat 库针对 5.x 进行了测试,这与宣传的一样。
        【解决方案15】:

        最简单的方法是定义轨道色调,并将色调模式设置为 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>
        

        【讨论】:

          【解决方案16】:

          您可以为开关小部件制作自定义样式 在为其自定义样式时默认使用颜色重音

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

          【讨论】:

            【解决方案17】:

            这对我有用 -:

            1.values/styles.xml中的代码-:

             <style name="SwitchTheme" parent="Theme.AppCompat.Light">
                <item name="android:colorControlActivated">#148E13</item>
            </style>
            

            2.在 layout 文件中的 switch 中添加以下代码行 -:

            android:theme="@style/SwitchTheme"
            

            【讨论】:

              【解决方案18】:

              你可以试试这个库,很容易改变开关按钮的颜色。
              https://github.com/kyleduo/SwitchButton

              【讨论】:

                【解决方案19】:

                尝试在这里找到正确答案:Selector on background color of TextView。 简而言之,您应该在 XML 中创建带有颜色的 Shape,然后在选择器中将其指定为“已选中”状态。

                【讨论】:

                • 不错的解决方案,但您知道我们如何动态更改颜色吗?
                • 只需将选择器设置为后台资源
                【解决方案20】:

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

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

                【讨论】:

                  【解决方案21】:

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

                  【讨论】:

                    【解决方案22】:

                    根据这里的一些答案的组合,这对我有用。

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

                    【讨论】:

                      【解决方案23】:

                      更改轨道和拇指可绘制的色调颜色。

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

                      【讨论】:

                        【解决方案24】:

                        Android Studio 3.6 解决方案:

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

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

                        【讨论】:

                          猜你喜欢
                          • 2020-10-20
                          • 2018-04-12
                          • 2021-06-09
                          • 2016-07-25
                          • 1970-01-01
                          • 1970-01-01
                          • 2013-12-24
                          • 2021-12-26
                          • 2023-03-15
                          相关资源
                          最近更新 更多