Кроме применение отдельных стилей к отдельным элементам, мы можем задавать стили для всего приложения или activity в виде тем. Тема предтавляет коллекцию атрибутов, которые применяются в целом ко всему приложению, классу activity или иерархии виджетов.
Мы можем сами создать тему. Однако Android уже предоставляет несколько предустановленных тем для стилизации приложения,
например, Theme.AppCompat.Light.DarkActionBar
и ряд других.
По умолчанию приложение уже применяет темы. Так, откроем файл AndroidManifest.xml. В нем мы можем увидеть следующее определение элемента application, представляющего приложение:
<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/Theme.ViewApp">
Задание темы происходит с помощью атрибута android:theme
. В данном случае используется ресурс, который называется в моем случае
Theme.ViewApp. По умолчанию файлы тем определены в папке res/values.
В частности, здесь можно найти условный каталог themes, в котором по умолчанию есть два элемента: themes.xml:
Один файл представляет светлую тему, а другой - темную. Например, откроем файл themes.xml со светлой темой:
<resources xmlns:tools="http://schemas.android.com/tools"> <!-- Base application theme. --> <style name="Theme.ViewApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <!-- Primary brand color. --> <item name="colorPrimary">@color/purple_500</item> <item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorOnPrimary">@color/white</item> <!-- Secondary brand color. --> <item name="colorSecondary">@color/teal_200</item> <item name="colorSecondaryVariant">@color/teal_700</item> <item name="colorOnSecondary">@color/black</item> <!-- Status bar color. --> <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> <!-- Customize your theme here. --> </style> </resources>
Здесь мы можем увидеть, что тема определяется как и стиль с помощью элемента style.. Атрибут parent указывает на родительскую тему, от которой текущая тема берет все стилевые характеристики. То есть тема "Theme.ViewApp" использует другую тему - "Theme.MaterialComponents.DayNight.DarkActionBar". И кроме того, определяет ряд своих собственных стилей.
Также можно заметить, что здесь определяются не только характеристики для атрибутов, но и семантические имена, например, colorPrimary
, которому сопоставлен ресурс "@color/purple_500".
При необходимости мы можем изменить эти характеристики или дополнить тему новыми стилевыми характеристиками. Например, изменим цвет свойства colorPrimary
, которое применяется в том числе
в качестве фонового цвета заголовка и кнопки:
<item name="colorPrimary">#1565C0</item>
И соответственно изменится цвет по умолчанию для фона заголовка и кнопки:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello Android" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Вместо использования встроенных тем мы можем создать свою. Для этого добавим в папку res/values новый файл mythemes.xml и определим в нем следующее содержимое:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="MyTheme" parent="Theme.AppCompat.Light"> <item name="android:textColor">#FF018786</item> <item name="android:textSize">28sp</item> </style> </resources>
Итак, мы создали стиль "MyTheme", который унаследован от стиля Theme.AppCompat.Light
. В этом стиле мы переопределили
два свойства: высоту шрифта (textSize) - 28sp, а также цвет текста (textColor) - #FF018786
.
Теперь определим этот стиль в качестве темы приложения в файле AndroidManifest.xml:
<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/MyTheme"><!-- применение темы -->
Пусть у нас будет следующая разметка в activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView1" android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="center" android:text="Android Lollipop" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@+id/textView2" /> <TextView android:id="@+id/textView2" android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="center" android:text="Android Marshmallow" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toTopOf="@+id/textView3" app:layout_constraintTop_toBottomOf="@+id/textView1" /> <TextView android:id="@+id/textView3" android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="center" android:text="Android Nougat" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" /> </androidx.constraintlayout.widget.ConstraintLayout>
Как видно, для элементов TextView не устанавливается атрибут textSize
и textColor
, однако поскольку они определены в теме,
которая применяется глобально к нашему приложению, то элементы TextView будут подхватывать эти стилевые характеристики:
Выше темы применялись глобально ко всему приложению. Но также можно применить их к отдельному классу Activity. Для этого надо подкоррективать файл манифеста AndroidManifest. Например:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.viewapp" android:versionCode="1" android:versionName="1.0"> <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/Theme.ViewApp"> <activity android:name=".MainActivity" android:theme="@style/MyTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Атрибут android:theme элемента <activity>
указывает на применяемую к MainActivity тему. То есть глобально к приложению применяется
тема "Theme.ViewApp", а к MainActivity - "MyTheme".
Также можно применить тему к иерархии виджетов, установив атрибут android:theme у элемента, к которому (включая его вложенные элементы) мы хотим применить тему. Например, примение темы к ConstraintLayout и ее элементам:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:theme="@style/MyTheme"> <TextView android:id="@+id/textView1" android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="center" android:text="Android Lollipop" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>