Как изменить цвет SwitchCompat
В моем приложении есть несколько переключателей с разными цветами, и для изменения их цветов я использовал настраиваемый селектор для каждого переключателя.
Когда была выпущена новая библиотека AppCompat v21, появился новый элемент управления android.support.v7.widget.SwitchCompat.
Можно ли изменить цвет SwitchCompat без использования рисования, например с использованием XML или кода?
8 ответов
AppCompat придает тонировку:
Во-первых, вы должны взглянуть на статью appCompat lib там и на различные атрибуты, которые вы можете установить:
colorPrimary: основной фирменный цвет для приложения. По умолчанию этот цвет применяется к фону панели действий.
colorPrimaryDark: темный вариант основного фирменного цвета. По умолчанию этот цвет применяется к строке состояния (через statusBarColor) и к панели навигации (через navigationBarColor).
colorAccent: яркое дополнение к основной цветовой гамме. По умолчанию это цвет, применяемый к элементам управления каркасом (через colorControlActivation).
colorControlNormal: цвет, применяемый к элементам управления каркаса в их нормальном состоянии.
colorControlActivation: цвет, применяемый к элементам управления каркаса в их активированном состоянии (например, проверено, включено).
colorControlHighlight: цвет, применяемый к элементам управления каркасом (например, рябь, селекторы списка).
colorButtonNormal: цвет, применяемый к кнопкам рамки в их нормальном состоянии.
colorSwitchThumbNormal: цвет, применяемый к каркасу, переключает большие пальцы в их обычное состояние. (выключить)
Если все пользовательские параметры одинаковы в одном действии:
С помощью предыдущих атрибутов вы можете определить свою собственную тему для каждого вида деятельности:
<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 работает путем перехвата любой разметки макета и вставки на его место специальной версии виджета с учетом оттенков (см. Статью Криса Бэйнса об этом), вы не можете применять собственный стиль к каждому переключателю XML-файла макета. Вы должны установить пользовательский контекст, который будет переключаться с правильными цветами.
-
Чтобы сделать это до версии 5.0, вам нужно создать контекст, который наложит глобальную тему на обычаи, а затем программно создайте параметры:
ContextThemeWrapper ctw = ContextThemeWrapper(getActivity(), R.style.Color1SwitchStyle);
SwitchCompat sc = new SwitchCompat(ctw)
По состоянию на AppCompat v22.1
Вы можете использовать следующее XML
чтобы применить тему к виджету переключения:
<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
(так же, как одно использование для объявления активности в манифесте). Основываясь на другом посте Криса Бэйнса, с последним вы сможете определить собственную тему непосредственно в представлении из вашего макета XML:
<android.support.v7.widget.SwitchCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="@style/Color1SwitchStyle"/>
Чтобы изменить цвет дорожки SwitchCompat
Благодаря vine'th я дополняю свой ответ ссылкой на SO-ответ, который объясняет, как указать передний план трека, когда переключатель выключен, он там.
Хорошо, извините, но большинство из этих ответов неполные или содержат небольшую ошибку. Очень полный ответ от @ austyn-mahoney является правильным и источником этого ответа, но он сложный, и вы, вероятно, просто хотите стилизовать переключатель. "Стилизация" управления в разных версиях Android - это эпическая боль в заднице. После нескольких дней работы над проектом с очень жесткими конструктивными ограничениями я, наконец, сломался и написал тестовое приложение, а затем по-настоящему копал и тестировал различные решения для стилевых переключателей и флажков, так как когда дизайн имеет один это часто имеет другой. Вот что я нашел...
Во-первых: вы не можете стилизовать ни одну из них, но вы можете применить тему ко всем или только к одной из них.
Второе: вы можете делать все это из XML, и вам не нужен второй файл values-v21/styles.xml.
Третье: когда дело доходит до коммутаторов, у вас есть два основных варианта, если вы хотите поддерживать более старые версии Android (как, я уверен, вы делаете)...
- Вы можете использовать
SwitchCompat
и вы сможете заставить его выглядеть одинаково на разных платформах. - Вы можете использовать
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>
styles.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_18:
Я думаю, что ответ в ссылке ниже лучше
Как изменить цвет дорожки SwitchCompat
<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
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"/>
Whoopsies. Этот пост дал мне представление о моей ошибке... надеюсь, если кто-то наткнется на это, он поможет им, как и я. Спасибо Gaëtan Maisse за ваш ответ
Чтобы лучше контролировать цвет дорожки (нет API
контролируемые альфа-изменения) я продлил 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:theme одновременно (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>
Будьте осторожны с известной ошибкой с SwitchCompat
Это ошибка с поврежденным файлом в drawable-hdpi на AppCompat https://code.google.com/p/android/issues/detail?id=78262
Чтобы исправить это, просто переопределите его с этими 2 файлами https://github.com/lopespm/quick-fix-switchcompat-resources Добавьте его в свой каталог drawable-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
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>