Стили и темы

Попробуйте способ «Композиции»
Jetpack Compose — рекомендуемый набор инструментов для разработки пользовательского интерфейса для Android. Узнайте, как работать с темами в Compose.

Стили и темы на Android позволяют отделить детали дизайна вашего приложения от структуры и поведения пользовательского интерфейса, аналогично таблицам стилей в веб-дизайне.

Стиль — это набор атрибутов, определяющих внешний вид отдельного View . Стиль может определять такие атрибуты, как цвет шрифта, размер шрифта, цвет фона и многое другое.

Тема — это набор атрибутов, применяемых ко всему приложению, активности или иерархии представлений, а не только к отдельному представлению. При применении темы каждое представление в приложении или активности применяет все поддерживаемые им атрибуты темы. Темы также могут применять стили к элементам, не относящимся к представлениям, таким как строка состояния и фон окна.

Стили и темы объявляются в файле ресурсов стилей в res/values/ , обычно называемом styles.xml .

Рисунок 1. Две темы, примененные к одному и тому же действию: Theme.AppCompat (слева) и Theme.AppCompat.Light (справа).

Темы против стилей

Темы и стили во многом схожи, но используются для разных целей. Темы и стили имеют одинаковую базовую структуру — пару «ключ-значение», которая сопоставляет атрибуты с ресурсами .

Стиль определяет атрибуты для определённого типа представления. Например, один стиль может определять атрибуты кнопки. Каждый атрибут, указанный в стиле, можно задать в файле макета. Извлечение всех атрибутов в стиль упрощает их использование и поддержку в нескольких виджетах.

Тема определяет набор именованных ресурсов, на которые могут ссылаться стили, макеты, виджеты и т. д. Темы присваивают ресурсам Android семантические имена, например colorPrimary .

Стили и темы должны работать вместе. Например, у вас может быть стиль, который определяет, что одна часть кнопки — colorPrimary , а другая — colorSecondary . Фактические определения этих цветов содержатся в теме. Когда устройство переходит в ночной режим, ваше приложение может переключиться со «светлой» темы на «тёмную», изменив значения всех названий ресурсов. Вам не нужно менять стили, поскольку они используют семантические имена, а не конкретные определения цветов.

Дополнительную информацию о том, как темы и стили работают вместе, можно найти в записи блога «Стили Android: темы против стилей» .

Создать и применить стиль

Чтобы создать новый стиль, откройте файл res/values/styles.xml вашего проекта. Для каждого стиля, который вы хотите создать, выполните следующие действия:

  1. Добавьте элемент <style> с именем, которое однозначно идентифицирует стиль.
  2. Добавьте элемент <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 Support Library ко всему приложению:

<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 Support Library версии 22.1, вы также можете указать атрибут android:theme для представления в файле макета. Это изменяет тему для этого представления и всех его дочерних представлений, что полезно для изменения цветовых палитр темы в определённой части интерфейса.

В предыдущих примерах показано, как применить тему, например, Theme.AppCompat , предоставленную библиотекой поддержки Android. Однако обычно требуется настроить тему в соответствии с фирменным стилем вашего приложения. Лучший способ сделать это — расширить стили из библиотеки поддержки и переопределить некоторые атрибуты, как описано в следующем разделе.

Иерархия стилей

Android предоставляет множество способов настройки атрибутов в вашем приложении. Например, вы можете задать атрибуты непосредственно в макете, применить стиль к представлению, применить тему к макету и даже задать атрибуты программно.

Выбирая стиль для своего приложения, учитывайте иерархию стилей Android. В целом, для обеспечения единообразия старайтесь максимально использовать темы и стили. Если вы указываете одни и те же атрибуты в нескольких местах, следующий список определяет, какие атрибуты будут применены в конечном итоге. Список упорядочен по приоритету от самого высокого к самому низкому.

  1. Применение стилей на уровне символов или абзацев с использованием текстовых диапазонов к классам, производным от TextView .
  2. Применение атрибутов программным способом.
  3. Применение отдельных атрибутов непосредственно к представлению.
  4. Применение стиля к представлению.
  5. Стиль по умолчанию.
  6. Применение темы к коллекции представлений, действию или всему приложению.
  7. Применение определенных стилей, специфичных для представления, например, установка TextAppearance для TextView .

Рисунок 2. Стилизация из span переопределяет стилизацию из 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>

Вы также можете расширить стили виджетов, как и любой другой стиль , а затем применить свой собственный стиль виджета в своем макете или теме.

Дополнительные ресурсы

Чтобы узнать больше о темах и стилях, ознакомьтесь со следующими дополнительными ресурсами:

Записи в блоге