如何从 AppCompat 库更改 Switch Compat 的颜色

在我的应用程序中,我有一些不同颜色的开关控件,为了改变它们的颜色,我使用了多个自定义的可绘制选择器。

随着 AppCompat v21库的发布,引入了一个新的 android.support. v7.widget. SwitchCompat 控件。

有没有可能在不使用客户可绘制选择器的情况下,通过编程方式改变 Switch Compat 的颜色,但使用 XML 或代码?

137987 次浏览

AppCompat 着色属性:

首先,您应该看一下 appCompat lib 文章 那里和您可以设置的不同属性:

ColorPrimary : 应用程序的主品牌颜色。默认情况下,这是应用于操作栏背景的颜色。

Color PrimaryDark : 主品牌颜色的深色变体。默认情况下,这是应用于状态栏(通过 statusBarColor)和导航栏(通过导航 BarColor)的颜色。

Color Accent : 对主品牌颜色的明亮补充。默认情况下,这是应用于框架控件的颜色(通过 color ControlActivated)。

ColorControlNormal : 应用于框架控件的正常状态的颜色。

ColorControlActivated : 应用于框架控件处于激活(例如,选中,打开)状态的颜色。

ColorControlHighlight : 应用于框架控件突出显示的颜色(例如涟漪、列表选择器)。

ColorButtonNormal : 应用于框架按钮正常状态的颜色。

应用于框架的颜色将拇指切换到正常状态。(关闭)


如果单个活动中的所有自定义切换都相同:

使用以前的属性,您可以为每个活动定义自己的主题:

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

以及:

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

如果您希望在单个活动中有不同的自定义开关:

由于 appcompat 中的小部件着色是通过拦截任何布局膨胀并在其位置插入一个特殊的着色感知版本(参见 Chris Banes 贴出来)来实现的,因此你不能对布局 xml 文件的每个开关应用自定义样式。您必须设置一个自定义上下文,将色调开关与正确的颜色。

--

要为 前5.0做到这一点,您需要创建一个上下文,覆盖全局主题与习惯属性,然后创建您的开关编程:

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

从 AppCompat v22.1开始,您可以使用以下 XML将主题应用到 switch 小部件:

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

自定义切换主题:

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

--

Android 5.0上,它看起来像是一个新的视图属性: android:theme(与在清单中声明活动的用法相同)。基于另一个 Chris Banes 邮寄,使用后者,您应该能够从您的布局 xml 中直接在视图上定义自定义主题:

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

更改 Switch Compat 的跟踪颜色

感谢万能,我完成了我的答案与一个链接到 SO 的答案,解释了如何指定的轨道前景时,开关关闭,它的 那里

小心 Switch Compat 的已知错误

这是 AppCompat 上的一个错误,其中包含一个已损坏的文件,该文件位于 draable-hdpi 中 Https://code.google.com/p/android/issues/detail?id=78262

要修复它,只需用这两个文件覆盖它 Https://github.com/lopespm/quick-fix-switchcompat-resources 将它添加到您的目录 draable-hdpi 中

XML

<android.support.v7.widget.SwitchCompat
android:id="@+id/dev_switch_show_dev_only"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>

在 Java 上什么都不需要

所以有时候我缺乏脑细胞:

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

不应用主题,因为样式是不正确的。我应该使用应用程序: 主题: P

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

哎呀。这篇文章让我认识到了自己的错误... ... 希望如果有人偶然发现了这篇文章,它会像对我一样对他们有所帮助。谢谢 Gaëtan Maisse 的回答

我认为下面的链接中的答案更好

如何更改 Switch Compat 的跟踪颜色

<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.widget.SwitchCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/adamSwitch"
android:textColor="@color/top_color"
android:textAppearance="@color/top_color"
android:gravity="center"
app:showText="true"
app:theme="@style/Custom.Widget.SwitchCompat"
app:switchPadding="5dp"
/>

在 style.xml 中

<style name="Custom.Widget.SwitchCompat" parent="Widget.AppCompat.CompoundButton.Switch" >
<item name="android:textColorPrimary">@color/blue</item>  <!--textColor on activated state -->
</style>

好的,我很抱歉,但是这些答案大部分是不完整的,或者有一些小错误。来自@austyn-mahoney 的完整答案是正确的,也是这个答案的来源,但是它很复杂,你可能只想设计一个开关。在不同版本的安卓系统上进行“样式化”控制是一件让人头疼的事情。在一个设计限制非常严格的项目上折腾了好几天之后,我终于崩溃了,写了一个测试应用程序,然后深入研究并测试了各种各样的样式开关和复选框的解决方案,因为当一个设计有一个时,它通常会有另一个。这是我发现的。

首先: 实际上你不能设计它们中的任何一个,但是你可以将一个主题应用到它们中的所有,或者仅仅是其中的一个。

第二: 您可以从 XML 完成所有操作,并且不需要第二个值-v21/styles.XML。

第三: 谈到开关,如果你想支持旧版本的 Android,你有两个基本的选择(我相信你一定会这么做) ..。

  1. 您可以使用 SwitchCompat,并且您将能够使它在不同的平台上看起来一样。
  2. 你可以使用 Switch,你将能够与你的主题的其余部分主题它,或者只是那个特定的开关,在旧版本的 Android 上,你只会看到一个没有样式的旧的方形开关。

现在来看看简单的参考代码。如果您再次创建一个简单的 Hello World!把这个代码放进去,你就可以尽情地玩了。所有这些在这里都是陈述,所以我将只包括活动和样式的 XML..。

Activity _ main.xml...

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.kunai.switchtest.MainActivity">


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="'Styled' SwitchCompat" />


<android.support.v7.widget.SwitchCompat
android:id="@+id/switch_item"
android:layout_width="wrap_content"
android:layout_height="46dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:checked="true"
android:longClickable="false"
android:textOff="OFF"
android:textOn="ON"
app:switchTextAppearance="@style/BrandedSwitch.text"
app:theme="@style/BrandedSwitch.control"
app:showText="true" />


</RelativeLayout>


<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.kunai.switchtest.MainActivity">


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Themed SwitchCompat" />


<android.support.v7.widget.SwitchCompat
android:id="@+id/switch_item2"
android:layout_width="wrap_content"
android:layout_height="46dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:checked="true"
android:longClickable="false" />


</RelativeLayout>


<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.kunai.switchtest.MainActivity">


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Themed Switch" />


<Switch
android:id="@+id/switch_item3"
android:layout_width="wrap_content"
android:layout_height="46dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:checked="true"
android:longClickable="false"
android:textOff="OFF"
android:textOn="ON"/>


</RelativeLayout>


<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.kunai.switchtest.MainActivity">


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="'Styled' Switch" />


<Switch
android:id="@+id/switch_item4"
android:layout_width="wrap_content"
android:layout_height="46dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:checked="true"
android:longClickable="false"
android:textOff="OFF"
android:textOn="ON"
android:theme="@style/BrandedSwitch"/>


</RelativeLayout>


<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.kunai.switchtest.MainActivity">


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="'Styled' CheckBox" />


<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="46dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:checked="true"
android:longClickable="false"
android:theme="@style/BrandedCheckBox"/>


</RelativeLayout>


<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.kunai.switchtest.MainActivity">


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Themed CheckBox" />


<CheckBox
android:id="@+id/checkbox2"
android:layout_width="wrap_content"
android:layout_height="46dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:checked="true"
android:longClickable="false"/>


</RelativeLayout>

Xml...

<resources>


<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#3F51B5</item>
<item name="colorPrimaryDark">#303F9F</item>
<item name="colorAccent">#FF4081</item>
</style>


<style name="BrandedSwitch.control" parent="Theme.AppCompat.Light">
<!-- active thumb & track color (30% transparency) -->
<item name="colorControlActivated">#e6e600</item>
<item name="colorSwitchThumbNormal">#cc0000</item>
</style>


<style name="BrandedSwitch.text" parent="Theme.AppCompat.Light">
<item name="android:textColor">#ffa000</item>
<item name="android:textSize">9dp</item>
</style>


<style name="BrandedCheckBox" parent="AppTheme">
<item name="colorAccent">#aaf000</item>
<item name="colorControlNormal">#ff0000</item>
</style>


<style name="BrandedSwitch" parent="AppTheme">
<item name="colorAccent">#39ac39</item>
</style>

我知道,我知道,你太懒了,不想构建这个,你只是想让你的代码写好并签入,这样你就可以关闭这个该死的 Android 兼容性错误,这样你团队中的设计师就会最终感到高兴。我明白了。这是它运行时的样子。

API _ 21:

API 21

API _ 18:

API18

为了更好地控制音轨颜色(没有 API控制的 alpha 变化) ,我扩展了 SwitchCompat并以编程方式设计元素的样式:

    public class CustomizedSwitch extends SwitchCompat {


public CustomizedSwitch(Context context) {
super(context);
initialize(context);
}


public CustomizedSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
}


public CustomizedSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context);
}


public void initialize(Context context) {
// DisplayMeasurementConverter is just a utility to convert from dp to px and vice versa
DisplayMeasurementConverter displayMeasurementConverter = new DisplayMeasurementConverter(context);
// Sets the width of the switch
this.setSwitchMinWidth(displayMeasurementConverter.dpToPx((int) getResources().getDimension(R.dimen.tp_toggle_width)));
// Setting up my colors
int mediumGreen = ContextCompat.getColor(context, R.color.medium_green);
int mediumGrey = ContextCompat.getColor(context, R.color.medium_grey);
int alphaMediumGreen = Color.argb(127, Color.red(mediumGreen), Color.green(mediumGreen), Color.blue(mediumGreen));
int alphaMediumGrey = Color.argb(127, Color.red(mediumGrey), Color.green(mediumGrey), Color.blue(mediumGrey));
// Sets the tints for the thumb in different states
DrawableCompat.setTintList(this.getThumbDrawable(), new ColorStateList(
new int[][]{
new int[]{android.R.attr.state_checked},
new int[]{}
},
new int[]{
mediumGreen,
ContextCompat.getColor(getContext(), R.color.light_grey)
}));
// Sets the tints for the track in different states
DrawableCompat.setTintList(this.getTrackDrawable(), new ColorStateList(
new int[][]{
new int[]{android.R.attr.state_checked},
new int[]{}
},
new int[]{
alphaMediumGreen,
alphaMediumGrey
}));
}
}

每当我想使用 CustomizedSwitch,我只需要添加一个到我的 xml文件。

只是

 android:buttonTint="@color/primary"

我的同时使用 style 和 android: subject 的工作示例(API > = 21)

<android.support.v7.widget.SwitchCompat
android:id="@+id/wan_enable_nat_switch"
style="@style/Switch"
app:layout_constraintBaseline_toBaselineOf="@id/wan_enable_nat_label"
app:layout_constraintEnd_toEndOf="parent" />


<style name="Switch">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingEnd">16dp</item>
<item name="android:focusableInTouchMode">true</item>
<item name="android:theme">@style/ThemeOverlay.MySwitchCompat</item>
</style>


<style name="ThemeOverlay.MySwitchCompat" parent="">
<item name="colorControlActivated">@color/colorPrimaryDark</item>
<item name="colorSwitchThumbNormal">@color/text_outline_not_active</item>
<item name="android:colorForeground">#42221f1f</item>
</style>