Стили и темы в Android позволяют отделить детали дизайна приложения от структуры и поведения пользовательского интерфейса, подобно таблицам стилей в веб-дизайне.
Стиль – это набор атрибутов, определяющих внешний вид одного элемента View. Стиль может определять такие атрибуты, как цвет шрифта, размер шрифта, цвет фона и многое другое.
Тема – это набор атрибутов, которые применяются ко всему приложению, действию или иерархии View, а не только к отдельному объекту View. Когда вы применяете тему, каждое представление в приложении или действии применяет каждый из поддерживаемых атрибутов темы. Темы также могут применять стили к элементам, не относящимся к представлению, например к строке состояния и фону окна.
Стили и темы объявляются в файле ресурсов стилей в res/values/, который обычно называется styles.xml.
Рисунок 1. Две темы, примененные к одному и тому же действию:
Theme.AppCompat (слева) и Theme.AppCompat.Light (справа).
Темы и стили
Темы и стили во многом похожи, но используются для разных целей. Темы и стили имеют одинаковую базовую структуру – пару "ключ-значение", которая сопоставляет атрибуты с ресурсами.
Стиль определяет атрибуты для определенного типа представления. Например, один стиль может определять атрибуты кнопки. Каждый атрибут, который вы указываете в стиле, можно задать в файле макета. Извлечение всех атрибутов в стиль упрощает их использование и поддержку в нескольких виджетах.
Тема определяет набор именованных ресурсов, на которые могут ссылаться стили, макеты, виджеты и т. д. Темы присваивают семантические названия, например colorPrimary, ресурсам Android.
Стили и темы предназначены для совместной работы. Например, в стиле может быть указано, что одна часть кнопки имеет цвет colorPrimary, а другая – colorSecondary. Определения этих цветов задаются в теме. Когда устройство переходит в ночной режим, приложение может переключиться со светлой темы на тёмную, изменив значения для всех этих названий ресурсов. Вам не нужно менять стили, поскольку в них используются семантические названия, а не конкретные определения цветов.
Дополнительную информацию о том, как темы и стили работают вместе, можно найти в записи блога Android styling: themes vs styles.
Как создать и применить стиль
Чтобы создать стиль, откройте файл res/values/styles.xml проекта. Для каждого стиля, который вы хотите создать, выполните следующие действия:
- Добавьте элемент
<style>с уникальным названием стиля. - Добавьте элемент
<item>для каждого атрибута стиля, который вы хотите определить.nameв каждом элементе указывает атрибут, который вы используете в качестве атрибута XML в макете. Значение в элементе<item>– это значение атрибута.
Например, вы задали следующий стиль:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="GreenText" parent="TextAppearance.AppCompat"> <item name="android:textColor">#00FF00</item> </style> </resources>
Применить стиль к представлению можно следующим образом:
<TextView style="@style/GreenText" ... />
Каждый атрибут, указанный в стиле, применяется к этому представлению, если представление его принимает. Представление игнорирует все атрибуты, которые не принимает.
Однако вместо того, чтобы применять стиль к отдельным представлениям, обычно стили применяются в качестве темы для всего приложения, действия или коллекции представлений, как описано в другом разделе этого руководства.
Как расширить и настроить стиль
При создании собственных стилей всегда расширяйте существующий стиль из фреймворка или библиотеки поддержки, чтобы сохранить совместимость со стилями пользовательского интерфейса платформы. Чтобы расширить стиль, укажите его в атрибуте parent. Затем вы можете переопределить унаследованные атрибуты стиля и добавить новые.
Например, вы можете унаследовать внешний вид текста по умолчанию для платформы Android и изменить его следующим образом:
<style name="GreenText" parent="@android:style/TextAppearance"> <item name="android:textColor">#00FF00</item> </style>
Однако основные стили приложения всегда должны наследоваться из библиотеки поддержки Android. Стили в библиотеке поддержки обеспечивают совместимость за счет оптимизации каждого стиля для атрибутов пользовательского интерфейса, доступных в каждой версии. Названия стилей из библиотеки поддержки часто похожи на названия стилей платформы, но содержат AppCompat.
Чтобы унаследовать стили из библиотеки или собственного проекта, укажите название родительского стиля без части @android:style/, показанной в примере выше. Например, в следующем примере стили внешнего вида текста наследуются из библиотеки поддержки:
<style name="GreenText" parent="TextAppearance.AppCompat"> <item name="android:textColor">#00FF00</item> </style>
Вы также можете наследовать стили (кроме стилей платформы), расширив название стиля с помощью точечной нотации вместо атрибута parent. Для этого добавьте к названию стиля название стиля, который вы хотите унаследовать, разделив их точкой. Обычно это делается только при расширении собственных стилей, а не стилей из других библиотек. Например, следующий стиль наследует все стили от GreenText в предыдущем примере, а затем увеличивает размер текста:
<style name="GreenText.Large"> <item name="android:textSize">22dp</item> </style>
Вы можете наследовать стили таким образом сколько угодно раз, добавляя в цепочку новые названия.
Чтобы узнать, какие атрибуты можно объявить с помощью тега <item>, обратитесь к таблице "XML-атрибуты" в справочных материалах по различным классам. Все представления поддерживают XML-атрибуты из базового класса View, а многие представления добавляют свои собственные специальные атрибуты. Например, XML-атрибуты TextView включают атрибут android:inputType, который можно применить к текстовому представлению, получающему входные данные, например к виджету EditText.
Как применить стиль в качестве темы
Тема создается так же, как и стиль. Разница заключается в том, как вы его применяете: вместо применения стиля с атрибутом style в представлении вы применяете тему с атрибутом android:theme в теге <application> или теге <activity> в файле AndroidManifest.xml.
Например, вот как можно применить темную тему Material Design из библиотеки поддержки Android ко всему приложению:
<manifest ... > <application android:theme="@style/Theme.AppCompat" ... > </application> </manifest>
А вот как применить светлую тему только к одному действию:
<manifest ... > <application ... > <activity android:theme="@style/Theme.AppCompat.Light" ... > </activity> </application> </manifest>
Каждое представление в приложении или действии применяет поддерживаемые стили из тех, которые определены в заданной теме. Если представление поддерживает только некоторые атрибуты, объявленные в стиле, то оно применяет только эти атрибуты и игнорирует те, которые не поддерживает.
Начиная с Android 5.0 (уровень API 21) и библиотеки поддержки Android версии 22.1, вы также можете указать атрибут android:theme для представления в файле макета. Это изменяет тему для этого представления и любых дочерних представлений, что полезно для изменения цветовых палитр темы в определенной части вашего интерфейса.
В предыдущих примерах показано, как применить тему, например Theme.AppCompat, которая поставляется с библиотекой поддержки Android. Однако обычно тему настраивают в соответствии с брендом приложения. Лучший способ сделать это – расширить эти стили из библиотеки поддержки и переопределить некоторые атрибуты, как описано в следующем разделе.
Иерархия стилей
Android предоставляет множество способов задать атрибуты в приложении для Android. Например, вы можете задать атрибуты непосредственно в макете, применить стиль к представлению, применить тему к макету и даже задать атрибуты программно.
При выборе стиля приложения учитывайте иерархию стилей Android. Для единообразия рекомендуется использовать темы и стили. Если вы укажете одни и те же атрибуты в нескольких местах, то будут применены атрибуты, указанные в списке ниже. Список упорядочен по приоритету (от высокого к низкому).
- Применение стилей на уровне символов или абзацев с помощью текстовых фрагментов к классам, производным от
TextView. - Применение атрибутов программным способом.
- Применение отдельных атрибутов непосредственно к представлению.
- Применение стиля к представлению.
- Стиль по умолчанию.
- Применение темы к набору представлений, действию или всему приложению.
- Применение определенных стилей, например настройка
TextAppearanceдляTextView.
Рисунок 2. Стиль, заданный в span, переопределяет стиль, заданный в textAppearance.
TextAppearance
Одно из ограничений стилей заключается в том, что к объекту View можно применить только один стиль. Однако в TextView вы также можете указать атрибут TextAppearance, который работает аналогично стилю, как показано в следующем примере:
<TextView ... android:textAppearance="@android:style/TextAppearance.Material.Headline" android:text="This text is styled via textAppearance!" />
TextAppearance позволяет задать стиль текста, а View – стиль других элементов. Однако обратите внимание, что если вы определяете какие-либо текстовые атрибуты непосредственно в View или в стиле, эти значения переопределяют значения TextAppearance.
TextAppearance поддерживает подмножество атрибутов стилей, которые предлагает TextView. Полный список атрибутов приведен в статье TextAppearance.
Некоторые распространенные атрибуты TextView, которые не включены: lineHeight[Multiplier|Extra], lines, breakStrategy и hyphenationFrequency.
TextAppearance работает на уровне символов, а не абзацев, поэтому атрибуты, влияющие на весь макет, не поддерживаются.
Как настроить тему по умолчанию
Когда вы создаете проект в Android Studio, к вашему приложению по умолчанию применяется тема Material Design, как определено в файле styles.xml проекта. Этот стиль AppTheme расширяет тему из библиотеки поддержки и включает переопределения для атрибутов цвета, которые используются ключевыми элементами пользовательского интерфейса, такими как панель приложения и плавающая кнопка действия (если используется). Таким образом, вы можете быстро настроить цветовое оформление вашего приложения, обновив предоставленные цвета.
Например, ваш файл styles.xml выглядит следующим образом:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
Значения стилей – это ссылки на другие ресурсы цвета, определенные в файле res/values/colors.xml проекта. Это файл, который вы редактируете, чтобы изменить цвета.
Чтобы улучшить взаимодействие с пользователем, добавьте динамические и дополнительные пользовательские цвета. Подробнее об этом рассказывается в обзоре цветов Material Design.
Когда вы определитесь с цветами, обновите значения в res/values/colors.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Color for the app bar and other primary UI elements. --> <color name="colorPrimary">#3F51B5</color> <!-- A darker variant of the primary color, used for the status bar (on Android 5.0+) and contextual app bars. --> <color name="colorPrimaryDark">#303F9F</color> <!-- a secondary color for controls like checkboxes and text fields. --> <color name="colorAccent">#FF4081</color> </resources>
Затем вы можете переопределить любые другие стили. Например, вы можете изменить цвет фона активности следующим образом:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> ... <item name="android:windowBackground">@color/activityBackground</item> </style>
Список атрибутов, которые можно использовать в теме, приведен в таблице атрибутов на странице R.styleable.Theme. При добавлении стилей для представлений в макете вы также можете найти атрибуты в таблице "XML-атрибуты" в справочнике по классам представлений. Например, все представления поддерживают XML-атрибуты из базового класса View.
Большинство атрибутов применяется к определенным типам просмотров, а некоторые – ко всем. Однако некоторые атрибуты темы, перечисленные на странице R.styleable.Theme, применяются к окну действия, а не к представлениям в макете. Например, windowBackground изменяет фон окна, а windowEnterTransition определяет анимацию перехода, которая будет использоваться при запуске действия. Подробнее о том, как запустить действие с помощью анимации…
Библиотека поддержки Android также предоставляет другие атрибуты, которые можно использовать для настройки темы, расширенной из Theme.AppCompat, например атрибут colorPrimary, показанный в предыдущем примере. Их лучше всего просматривать в файле attrs.xml библиотеки.
В библиотеке поддержки также доступны другие темы, которые можно расширить вместо показанных в предыдущем примере. Посмотреть доступные темы можно в файле themes.xml библиотеки.
Добавьте стили для определенных версий
Если в новой версии Android добавлены атрибуты темы, которые вы хотите использовать, вы можете добавить их в свою тему, сохранив совместимость со старыми версиями. Вам понадобится ещё один файл styles.xml, сохраненный в каталоге values, который содержит модификатор версии ресурса:
res/values/styles.xml # themes for all versions res/values-v21/styles.xml # themes for API level 21+ only
Поскольку стили в файле values/styles.xml доступны для всех версий, ваши темы в values-v21/styles.xml могут наследовать их. Это означает, что вы можете избежать дублирования стилей, начав с "базовой" темы, а затем расширив ее в стилях для конкретной версии.
Например, чтобы объявить переходы между окнами для Android 5.0 (уровень API 21) и более поздних версий, необходимо использовать новые атрибуты. Базовая тема в res/values/styles.xml может выглядеть так:
<resources> <!-- Base set of styles that apply to all versions. --> <style name="BaseAppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/primaryColor</item> <item name="colorPrimaryDark">@color/primaryTextColor</item> <item name="colorAccent">@color/secondaryColor</item> </style> <!-- Declare the theme name that's actually applied in the manifest file. --> <style name="AppTheme" parent="BaseAppTheme" /> </resources>
Затем добавьте стили для конкретной версии в res/values-v21/styles.xml, как показано ниже:
<resources> <!-- extend the base theme to add styles available only with API level 21+ --> <style name="AppTheme" parent="BaseAppTheme"> <item name="android:windowActivityTransitions">true</item> <item name="android:windowEnterTransition">@android:transition/slide_right</item> <item name="android:windowExitTransition">@android:transition/slide_left</item> </style> </resources>
Теперь вы можете применить AppTheme в файле манифеста, и система выберет стили, доступные для каждой версии системы.
Подробнее о том, как использовать альтернативные ресурсы для разных устройств…
Как настроить стили виджета
У каждого виджета в фреймворке и библиотеке поддержки есть стиль по умолчанию. Например, если вы оформляете приложение с помощью темы из библиотеки поддержки, экземпляр Button оформляется с помощью стиля Widget.AppCompat.Button. Если вы хотите применить к кнопке другой стиль виджета, используйте атрибут style в файле макета. Например, в следующем фрагменте кода применяется стиль кнопки без границ:
<Button style="@style/Widget.AppCompat.Button.Borderless" ... />
Если вы хотите применить этот стиль ко всем кнопкам, вы можете объявить его в файле buttonStyle вашей темы следующим образом:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="buttonStyle">@style/Widget.AppCompat.Button.Borderless</item> ... </style>
Вы также можете расширить стили виджетов, как и любые другие стили, а затем применить собственный стиль виджета в макете или теме.
Дополнительные ресурсы
Чтобы узнать больше о темах и стилях, ознакомьтесь со следующими дополнительными ресурсами:
Записи в блоге
- Стилизация в Android: темы и стили
- Стили Android: общие атрибуты темы
- Стили Android: используйте атрибуты темы