Хабрахабр

Темы и стили в Android без магии. И как их готовить с SwitchCompat

В предыдущей статье мы рассмотрели как использовать темы и стили на уровне кода, на примере кастомной view. В этой статье давайте разберем несколько способов стилизации стандартного ui элемента, а в частности SwitchCompat.

Содержание

Введение
Новый стиль для switchStyle
Стиль в верстке
Стиль в теме. Тема назначается через Manifest.
Стиль в теме. Тема назначается программно.
Другие View

Введение

Не всегда оформление по умолчанию стандартного UI элемента устраивает дизайнера. Давайте разберем, как поменять внешний вид элемента на примере SwitchCompat.

Для решения задачи нам нужно:

  • Создать свой стиль для SwitchCompat.
  • Каким-то образом задать этот стиль SwitchCompat.

Назначить стиль SwitchCompat можно несколькими способами, например:

  • Указывать для каждой view в верстке экранов через атрибут style.
  • Создать тему с переопределенным атрибутом switchStyle и назначить эту тему в манифесте для всего приложения или конкретной активити. Это изменит внешний вид view для всего приложения/активити.
  • Тему также можно установить программно, в коде активити. При необходимости ее можно менять «на лету».

Новый стиль для SwitchCompat

AppCompat. В ресурсах создадим новый стиль MySwitchStyle, наследуем оформление от Widget. Switch, задав parent. CompoundButton. Можно и не наследовать, но тогда придется указать все значения, даже которые мы не планируем менять.

<style name="MySwitchStyle" parent = "Widget.AppCompat.CompoundButton.Switch">
</style>

Чтобы что-то изменить, надо переопределить требуемые атрибуты. Атрибуты можно посмотреть в документации.

Они указаны в виде, как если бы мы обращались к ним в коде (например, вот так R.styleable. В документации видим несколько атрибутов. Я расшифрую только часть из них, чтобы не было сомнений. SwitchCompat_android_thumb). Назначение остальных несложно понять из документации.

  • android:thumb — ресурс для подвижной части SwitchCompat
  • track — ресурс для неподвижной части SwitchCompat
  • thumbTint — позволяет окрашивать подвижную часть в нужные цвета в зависимости от состояния SwitchCompat
  • trackTint — позволяет окрашивать неподвижную часть в нужные цвета в зависимости от состояния SwitchCompat

В качестве примера изменим цвет thumb (кружочка) — пусть во включенном состоянии он будет оранжевым, в выключенном — зеленым. Некрасиво, но наглядно.

Файл selector_switch_thumb.xml Нам понадобится селектор в папке color наших ресурсов.

<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true" android:color = "@android:color/holo_orange_dark"/> <item android:color="@android:color/holo_green_light"/>
</selector>

Теперь зададим атрибут thumbTint в нашем стиле.

<style name="MySwitchStyle" parent = "Widget.AppCompat.CompoundButton.Switch"> <item name="thumbTint">@color/selector_switch_thumb</item>
</style>

Теперь все SwitchCompat, получившие каким-то образом стиль MySwitchStyle, будут выглядеть по-новому.

Стиль в верстке

Самый тривиальный и негибкий способ.

  • Стиль применяется при inflate ресурса layout.
  • Повлиять программно мы никак не можем.
  • Указывать каждый раз в верстке неудобно. И можем забыть.

<androidx.appcompat.widget.SwitchCompat android:text="Themed switch" style="@style/MySwitchStyle" android:layout_width="wrap_content" android:layout_height="wrap_content"/>

Стиль в теме. Тема назначается через Manifest

Создаем тему AppTheme и задаем значение атрибуту switchStyle. Значением является наш стиль MySwitchStyle.

<resources> <style name="CustomTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <!-- Задаем значение атрибуту switchStyle --> <item name="switchStyle">@style/MySwitchStyle</item> </style>
</resources>

Тема может быть указана в манифесте для всего приложения

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/CustomTheme"><!-- Тема для всего приложения -->
</application>

Или для конкретной активити

<activity android:name=".MainActivity" android:theme="@style/CustomTheme"><!-- Тема для активити -->
</activity>

Теперь все SwitchCompat будут иметь новый внешний вид. Без изменения в верстке.

  • Плюсы — Можем менять внешний вид для всего приложения сразу.
  • Минусы — налету менять не получится.

Стиль в теме. Тема назначается программно

Для того, чтобы установить тему для активити программно, нужно вызвать метод активити setTheme(themeResId).

Давайте менять тему активити в зависимости от состояния Switch.

class MainActivity : AppCompatActivity() override fun onCreate(savedInstanceState: Bundle?) { val isCustomThemeChecked = preference.getBoolean( KEY_CUSTOM_THEME_CHECKED, true ) if (isCustomThemeChecked) { setTheme(R.style.CustomTheme) } else { setTheme(R.style.StandardTheme) } super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) customThemeCheckbox.isChecked = isCustomThemeChecked customThemeCheckbox.setOnCheckedChangeListener { _, isChecked -> preference.edit() .putBoolean(KEY_CUSTOM_THEME_CHECKED, isChecked) .apply() recreate() } }
}

  1. Устанавливаем тему программно, вызвав setTheme. Метод надо вызывать до super.onCreate(savedInstanceState). В onCreate у нас происходит инициализация фрагментов (когда они есть).
  2. Задаем начальное состояние Switch в зависимости от темы.
  3. Устанавливаем листенер, который при изменении Switch меняет тему в настройках и перезапускает активити через метод активити recreate().

Результат

Остальной код

<resources> <style name="CustomTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="switchStyle">@style/MySwitchStyle</item> </style> <style name="StandardTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="MySwitchStyle" parent="Widget.AppCompat.CompoundButton.Switch"> <item name="thumbTint">@color/selector_switch_thumb</item> </style>
</resources>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" android:orientation="vertical"> <CheckBox android:text="CustomTheme" android:layout_width="match_parent" android:layout_height="wrap_content" android:saveEnabled="false" android:id="@+id/customThemeCheckbox"/> <androidx.appcompat.widget.SwitchCompat android:text="Themed switch" android:layout_marginTop="56dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/themedSwitch"/>
</LinearLayout>

Другие View

Чтобы переопределить стиль для SwitсhView для всего приложения, мы переопределили значение атрибута switchStyle, можно догадаться, что такие атрибуты есть и для других View.

Например:

  • editTextStyle
  • checkboxStyle
  • radioButtonStyle

Как их искать? Я просто смотрю исходники, через Android Studio.
Заходим в тему, зажимаем ctrl, кликаем на родителе нашей темы. Смотрим, как описывают тему ребята из Google. Смотрим, какой атрибут определяется и от какого стиля можно отнаследоваться. Пользуемся.

V7. Кусок из темы Base. AppCompat. Theme. Light.

<item name="editTextStyle">@style/Widget.AppCompat.EditText</item>
<item name="checkboxStyle">@style/Widget.AppCompat.CompoundButton.CheckBox</item>
<item name="radioButtonStyle"> @style/Widget.AppCompat.CompoundButton.RadioButton
</item>
<item name="buttonStyle">@style/Widget.AppCompat.Button</item>

Ресурсы

developer.android.com/guide/topics/ui/look-and-feel/themes

developer.android.com/reference/android/support/v7/widget/SwitchCompat.html#xml-attributes

S. P.

Код умышленно сокращен. Статья не претендует на полный справочник. Дальше все легко ищется в документации и в стандартных ресурсах. Я ставил задачу дать общее понимание — как это работает и зачем это нужно.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть