Змініть колір "включення" перемикача


156

Я використовую стандартне управління Switch з темою holo.light у програмі ICS.

Я хочу змінити виділений або на стан стану кнопки Toggle із стандартного світло-синього на зелений.

Це повинно бути легко, але я не можу зрозуміти, як це зробити.


Я насправді не бачу іншого способу, крім копіювання відповідних ресурсів платформи (файли селектора та * .png) та зміни стану "on", який можна малювати. Не забудьте Switchзгодом вказати на цей спеціальний селектор.
— МЗ.

Відповіді:


100

На сьогодні краще використовувати 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">

1
Хоча в той час не застосовується, це має бути прийнятою відповіддю!
— Ендрю Галлаш

Змінили це на прийняту відповідь, оскільки, здається, більш "сучасний" підхід до цього питання.
— JamesSugrue

1
Я спробував усе це, і жоден з них не змінив колір "включеного" для мого перемикача.
— Адам Джонс

31
'on' є colorAccent, 'off' є colorSwitchThumbNormal. Якщо ви використовуєте AppCompatтему, вам потрібно SwitchCompatскоріше використовувати Switch. Якщо ви використовуєте SDK 23+, ви можете використовувати android:thumbTintта android:thumbTintModeз ColorStateList.
— Том

1
@Tom plz відповість, що ці "android: thumbTint" речі працюватимуть на пристроях <23
— Shirish Herwade

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
Добре, за винятком colorControlActivate - він не встановлює колір доріжки, а лише великий палець.
— Покажчик Нуль

1
тут рішення для комутатора і SwitchCompat: stackoverflow.com/a/47036089/5869630
— roghayeh Хоссейні

Теги <style>, необхідні для запису в розділі res >> values ​​>> styles.xml та на XML-сторінці для <Switch ...>, слід додати лише рядок під назвою: android: topic = "@ style / SCBSwitch і мої кольори : colorControlActivate "> # ff0000 and colorSwitchThumbNormal"> # 00ff00 та android: colorForeground "> # 00ff00
— Бей

@OviTrif Чудовий! Вражає, як важко знайти просту подібну інформацію. Багато і багато відповідей, які я читав, і ніхто досі не давав робочої відповіді. Нарешті!
— jairhumber до

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

Я використовую підхід getThumbDravable / getTrackDravable, щоб створити комутатор, коли обидва стану мають один і той же колір - іншими словами, комутатор щось не вмикає / відключає, але використовується для вибору між двома альтернативами.
— Natix

4
Зрозуміло, що DravableCompat.setTintList дозволить йому працювати на попередніх пристроях. Я закликаю: DravableCompat.setTintList (switchCompat.getThumbDravable (), foregroundState);
— Олексій

Відредагуйте відповідь, щоб включити рішення DravableCompat. Це прекрасно працює!
— Дмитро Каратаєв

API 23+: switchInput.setThumbTintList(buttonStates); працює і для Nougat. API 21-22: Використовуйте DravableCompat, як запропонував @Alexey. Він switchInput.setButtonTintList(buttonStates);не працював для мене, він не забарвлював стани мого Switch. API нижче 21: switchInput.getThumbDrawable().setColorFilter(someColor, PorterDuff.Mode.SrcIn); Це працювало для мене. Я працював і з Xamarin, тому перекладіть їх на C # в Android-рендері, якщо ви використовуєте Xamarin.Forms.
— Черубі

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:

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


17
Це змінює колір великого пальця, незалежно від того, увімкнено чи вимкнено він.
— андроїд розробник

1
"Attribute thumbTint використовується лише в API рівня 21 і вище"
— norbDEV

6
@norbDEV використовувати додаток: thumbTint та додаток: trackTint за допомогою SwitchCompat з бібліотеки AppCompat.v7 для нижчого рівня API.
— Девід Даріас

Це працює, але що робити, якщо ви хочете змінити колір для великого пальця, залежно від того, увімкнено він чи вимкнено?
— TavernSenses

2
Якщо ви хочете використовувати thumbTint нижче 21 використання app:thumbTintзамість android:thumbTintі зміни switchзSwitchCompat
— Kavita_p

33

Створіть користувацький перемикач та замініть набірПеревірено, щоб змінити колір:

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

2
Перша публікація, яка насправді допомогла мені досягти спеціального кольору для переключення матеріалів, не використовуючи стиль чи теми. Дякую !
— Маккович

1
Приємно. У мене вже був власний індивідуальний перемикач, тому мені довелося лише перекрити метод setChecked, і всі вони автоматично змінили свої кольори. Спасибі від Іспанії.
— Хуліо

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

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


З якоїсь причини мені також довелося встановити "colorControlActivate" на те саме значення, але на POC цього було достатньо використовувати "colorAccent". Як це?
— андроїд розробник

22
<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 і вище
— wingear

1
Це 2020 рік. Мені справді цікаво, де в світі люди все ще використовують Android 21 і нижче?
— zeeshan

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

13

Можливо, це трохи пізно, але для кнопок перемикача кнопка toogle не є відповіддю, ви повинні змінити параметр xml у перемикачі:

 android:thumb="your drawable here"

9

зробити мальованим "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>

Проблема цього рішення полягає в тому, що він також змінює кольори вибраного тексту тексту, а це не те, що я хочу.
— кодування

@codewing Звичайно, так і буде. Тому що це встановлено у світовій стилістиці. Щоб досягти своєї мети, потрібно знайти ідентифікатор подання цільового перегляду та змінити його атрибути.
— емен

Гаразд, це для позиції "Увімкнено". Як щодо зміни кольору великого пальця для положення «Вимкнено»?
— TavernSenses

7

Створіть власне 9-латне зображення та встановіть його як фон кнопки перемикання.

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


2
Так, міг би це зробити, але, звичайно, ОБОВ'ЯЗКОВО бути простішим способом? Можливо, селектори?
— JamesSugrue

Ні, немає простішого шляху. Ви не можете чарівно змінити колір зображення :)
— you786

Гарна думка. Я не до кінця зрозумів, як це працює, поки не заглянув глибше.
— JamesSugrue

@Denizen, ти впевнений? Якщо так, опублікуйте відповідь, і я проголосую за неї.
— you786

@Denizen Видаліть ваш коментар. Android Switch завжди повертає нуль для getBackground (), я витрачав це 30 хвилин, намагаючись це зробити.
— Shirish Herwade

5

Рішення, запропоноване арломедією, працювало для мене. Про свою проблему з додатковим простором я вирішив видалити всі накладки на комутатор.

EDIT

За запитом, ось що у мене є.

У файлі компонування мій перемикач знаходиться всередині лінійного макета та після 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 з кольором, а потім призначити його стані "перевірено" у вашому селекторі.


Гарне рішення, але чи знаєте ви, як можна динамічно змінити колір?
— inverted_index

Вам просто потрібно встановити селектор як фоновий ресурс
— Шамм

1

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

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

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

Майте на увазі, що якщо ви використовуєте стандарт Switchі androidпростір імен для цих атрибутів, він буде працювати лише для API 23 і пізніших версій, тому використовуйте SwitchCompatз appпростором іменxmlns:app="http://schemas.android.com/apk/res-auto" як універсальним рішенням.

Результат:

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


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)

-1

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

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

Змінює колір тексту в кольорі, визначеному у файлі XML (yourColor).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.