Изменить «вкл» цвет переключателя

156

Я использую стандартный элемент управления Switch с темой holo.light в приложении ICS.

Я хочу изменить выделенный цвет или цвет состояния кнопки переключения со стандартного голубого на зеленый.

Это должно быть легко, но я не могу понять, как это сделать.

JamesSugrue
источник
На самом деле я не вижу другого способа, кроме как скопировать соответствующие ресурсы платформы (файлы селектора и * .png) и изменить отображаемое состояние «включено». Не забудьте Switchпотом указать на этот пользовательский селектор.
МХ.

Ответы:

101

На данный момент лучше использовать SwitchCompat из библиотеки AppCompat.v7. Затем вы можете использовать простой стиль, чтобы изменить цвет ваших компонентов.

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>

ref: Блог разработчиков 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">
SubChord
источник
1
Хотя это не применимо в то время, это должен быть принятый ответ!
Эндрю Галлаш
Изменили это на принятый ответ, так как кажется более «современный» подход к этому вопросу.
JamesSugrue
1
Я попробовал все это, и ни один из них не изменил цвет состояния «включено» для моего переключателя.
Адам Джонс
31
«включен» есть colorAccent, «выключен» есть colorSwitchThumbNormal. При использовании AppCompatтемы, вы должны использовать, SwitchCompatа не Switch. Если вы используете SDK 23+, вы можете использовать android:thumbTintи android:thumbTintModeс ColorStateList.
Том
1
@Tom plz ответит, что эти 'android: thumbTint' вещи будут работать на устройствах <23
Шириш Хервейд
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
Хорошо, за исключением colorControlActivation - он не устанавливает цвет дорожки, только цвет большого пальца.
Указатель нулевой
1
Вот решение для Switch и SwitchCompat: stackoverflow.com/a/47036089/5869630
roghayeh hosseini
Теги <style> должны быть записаны в res >> values ​​>> styles.xml и на странице XML для <Switch ...> вы должны добавить только строку с именем: android: theme = "@ style / SCBSwitch, и мои цвета : colorControlActivation "> # ff0000 and 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

Как сказал Херувим в комментариях, мы можем использовать новое, 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);
}
arlomedia
источник
Я использую подход getThumbDrawable / getTrackDrawable для создания переключателя, в котором оба состояния имеют одинаковый цвет - другими словами, переключатель не включает и не отключает что-то, а используется для выбора между двумя альтернативами.
Natix
4
Получил, что DrawableCompat.setTintList позволит ему работать на предыдущих устройствах. Я вызываю: DrawableCompat.setTintList (switchCompat.getThumbDrawable (), foregroundState);
Алексей
Пожалуйста, отредактируйте ответ, чтобы включить решение DrawableCompat. Работает отлично!
Дмитрий Каратаев
API 23+: switchInput.setThumbTintList(buttonStates); работает и для Nougat. API 21-22: используйте DrawableCompat в соответствии с рекомендациями @Alexey. Он switchInput.setButtonTintList(buttonStates);не работал для меня, он не окрашивал состояния для моего Switch. API ниже 21: switchInput.getThumbDrawable().setColorFilter(someColor, PorterDuff.Mode.SrcIn); это сработало для меня. Я также работал с Xamarin, поэтому, если вы используете Xamarin.Forms, переведите их в C # в средствах визуализации Android.
Херувим
37

Чтобы изменить стиль Switch без использования style.xml или Java-кода, вы можете настроить переход на макет 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: thumbTint и android: trackTint, который позволил вам настроить цвет

Это визуальный результат для этого XML:

введите описание изображения здесь

Кевин ABRIOUX
источник
17
Это меняет цвет большого пальца, независимо от того, включен он или нет.
Android-разработчик
1
«Атрибут thumbTint используется только в API уровня 21 и выше»
norbDEV
6
@norbDEV использует app: thumbTint и app: trackTint с SwitchCompat из библиотеки AppCompat.v7 для более низкого уровня API.
Дэвид Дариас
Это работает, но что если вы хотите изменить цвет большого пальца, в зависимости от того, включен он или нет?
TavernSenses
2
Если вы хотите использовать thumbTint ниже 21 использование app:thumbTintвместо android:thumbTintи изменения switchсSwitchCompat
Kavita_p
33

Создайте пользовательский переключатель и переопределите 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();
            }
        }
    }
}
francisco_ssb
источник
2
Первый пост, который на самом деле помог мне добиться индивидуального цвета для переключения материалов без использования стиля или тем. Спасибо !
Мацкович
1
Ницца. У меня уже был свой настроенный Switch, поэтому мне пришлось только переопределить метод setChecked, и все они автоматически изменили свои цвета. Спасибо из Испании.
Хулио
23
<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>
wingear
источник
thumbTintприменяется только на Android API 21 и выше. Как, если я хочу изменить цвет ниже Android 21?
Джованка Бизано
developer.android.com/reference/android/support/v7/widget/… SwitchCompat обратно совместим с API 7 и выше
wingear
1
Это 2020 год. Мне действительно интересно, где в мире люди все еще используют Android 21 и ниже?
Зеешан
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" ... />

При этом он влияет ТОЛЬКО на цвет представлений, к которым вы хотите его применить.

Грег Эннис
источник
По какой-то причине мне также пришлось установить «colorControlActivation» на то же значение, но для POC этого было достаточно, чтобы использовать «colorAccent». Как придешь?
Android-разработчик
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);
    }
}
MCR
источник
13

Может быть, уже немного поздно, но для кнопок переключения кнопка toogle не является ответом, вы должны изменить drawable в параметре xml переключателя:

 android:thumb="your drawable here"
Golgorz
источник
9

сделать drawable "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 не сможет предложить ресурсы @drawable для trackTintили thumbTint. Нужно написать это вручную, и это работает.
Бенджамин Басмачи
По какой-то причине это единственный ответ, который надежно работает на моем Huawei. Спасибо!
einUsername
7

В Android Lollipop и выше определите его в стиле вашей темы:

<style name="BaseAppTheme" parent="Material.Theme">
    ...
    <item name="android:colorControlActivated">@color/color_switch</item>
</style>
Emen
источник
Проблема с этим решением состоит в том, что оно также меняет цвета моих выбранных текстовых сообщений, что не то, что я хочу.
кодингинг
@ Codewing Конечно, будет. Потому что это установлено в глобальных предпочтениях стиля. Чтобы достичь своей цели, нужно найти идентификатор представления целевого вида и изменить его атрибуты.
emen
ОК, это для позиции «Вкл». Как насчет изменения цвета большого пальца для положения «Выкл»?
TavernSenses
7

Создайте свое собственное изображение из 9 патчей и установите его в качестве фона кнопки переключения.

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

you786
источник
2
Да, мог бы сделать это, но наверняка должен быть более простой способ? Селекторы может быть?
JamesSugrue
Нет, проще нет. Вы не можете волшебным образом изменить цвет изображения :)
you786
Хорошая точка зрения. Я не до конца понял, как это работает, пока не посмотрел глубже.
JamesSugrue
@Denizen, ты уверен? Если так, напишите ответ, и я проголосую.
you786
@Denizen Пожалуйста, удалите свой комментарий. Android Switch всегда возвращает null для getBackground (), я потратил 30 минут, пытаясь это сделать.
Шириш Хервейд
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
Протестировано в Xamarin с использованием библиотеки AppCompat для таргетинга 5.x, и это сработало, как рекламировалось.
Alex.Ritna
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 . В двух словах вы должны создать Shape в XML с цветом, а затем присвоить ему состояние «флажок» в вашем селекторе.

Shamm
источник
Хорошее решение, но знаете ли вы, как мы можем динамически менять цвет?
inverted_index
Вам просто нужно установить переключатель в качестве фонового ресурса
Shamm
1

Я не знаю, как это сделать из Java, но если у вас есть стиль, определенный для вашего приложения, вы можете добавить эту строку в свой стиль, и у вас будет нужный мне цвет, я использовал # 3F51B5

<color name="ascentColor">#3F51B5</color>
erluxman
источник
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 Switchи androidпространство имен для этих атрибутов, он будет работать только для API 23 и позже, поэтому использование SwitchCompatс appпространством имен в xmlns:app="http://schemas.android.com/apk/res-auto"качестве универсального решения.

Результат:

введите описание изображения здесь

remain4life
источник
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)
ROHIT LIEN
источник
-1

Решение для Android Studio 3.6:

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

Изменяет цвет текста в определенном значении файла XML (yourColor).

ChristianYami
источник