如何更改SwitchCompat的轨道颜色

58

我尝试使用以下链接来更改SwitchCompat的颜色:

如何更改SwitchCompat的颜色

注意到我的开关的低对比度:

SwitchCompat

但是在更改了所有相关颜色值之后,SwitchCompat的轨迹(较亮的灰色)仍然相同。我不想改变外观,只想改变颜色。拇指是粉红色的,我希望轨迹有一些对比度。我错过了在styles.xml中定义某个值吗?

我尝试了这些值(随机非白色颜色):

<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>
...>
10个回答

163

我曾经遇到同样的问题并解决了它。

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

我阅读了应用程序兼容性代码,并且理解了它。

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

13
有没有办法设置不同的活动滑块颜色和活动轨道颜色?而不是在相同颜色上使用30%透明度差异。 - ir2pid
1
@ir2pid:你可以指定一个可绘制对象。 - vine'th
我在同一个活动中有多个开关,如何为它们设置不同的颜色? - Khurram Shehzad
请问你是如何阅读源代码的? 我下载了源代码,但没有找到关于这个类的任何信息。 你是通过这个链接来阅读的吗:https://android.googlesource.com/platform/frameworks/support/+/1949ae9aeaadf52ad7bd7bb74ca5419c67ea7f65/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java 你能分享一些阅读源代码的经验或方法吗? - Francis Bacon
2
androidx.appcompat.widget.SwitchCompat怎么样?我无法改变样式吗? - Duna

15

以下是使用AppCompat的方式程序化地更改特定 SwitchCompat 的轨迹(track)和拇指(thumb)的颜色。 对于此示例,我已将thumbColor硬编码为红色。 理想情况下,您会通过第二个方法参数设置颜色。

请注意,当开关被选中时,会显示涟漪效果。 涟漪颜色不会受到下面代码的影响。

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

10

如果您想自定义轨道的颜色,您可以使用这个解决方案。

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

checked_color和unchecked_color是你选择的颜色。

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>

布局文件

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

有用的解决方案 - Faisal Mohammad

6
使用 Material 组件库提供的 MaterialSwitch。
使用 materialThemeOverlay 属性来覆盖 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>

在布局中:

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

在此输入图片描述在此输入图片描述

  • 使用style属性:
  <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>

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

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

在布局中:

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

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

trackTint属性可以改变你的轨道颜色


4
如果你想在一个活动中使用多种颜色的开关,可以使用这个解决方案(基于@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>

其中@color/custom是当切换开关激活时,拇指的颜色。

然后按照以下方式将此主题应用于您的SwitchCompat:

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

androidx.appcompat.widget.SwitchCompat - 迁移到androidX时无法更改 - Duna

2
以下是开发人员如何更改SwitchCompat的轨道可绘制内容的方法:
首先,在根布局中编写xmlns:SwitchCompat="http://schemas.android.com/apk/res-auto"
然后:
    <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>

最初的回答
简单易懂...

0

我曾经遇到过同样的问题。最终通过这段 Kotlin 代码编程解决了它。

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

而函数调用为

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

你也可以创建一个扩展函数:

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

这样调用会更容易

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

0

SwitchCompat是一个Material Design小部件。 当我的活动扩展AppCompatActivity并且android:theme="@style/mySwitch"时,它可以工作。


0

只需使用colorControlActivated来设置SwitchCompat的轨道和拇指的颜色。

如果未设置,则默认的colorControlActivated颜色将使用colorAccent。 (从经验来看,仍然找不到源代码中的位置)。

源代码已更改,但仍不像@Ovidiu所说。 但仍然感谢他让我知道从源代码中找到答案。

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

最终将调用以下方法。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接