Android material theme overlay

Using Material Theme Overlay

14 October 2019

I watched Developing Themes with Style a couple of weeks ago and learned everything about themes and styles that I’d deferred for the last six years.

@chrisbanes 😍 this diagram (and preceding guide) is what I needed in my life. right now. pic.twitter.com/vsKBILYZyr

One of the concepts that was new to me was theme overlays. It’s a powerful technique that allows us to override only the attributes that are specified in the overlay itself.

The typical way to apply a theme overlay is using the android:theme attribute on our view. This post summarises how we can do this, as well as introducing materialThemeOverlay , a theme attribute that (kind of) lets us set a theme overlay on a default style.

Using Theme Overlays

In AndroidManifest.xml , we’ll set the app theme by specifying the theme attribute on the application element, android:theme=»@style/Theme.Demo» . Our theme defines the colorPrimary theme attribute:

Our layout has two buttons, which are now red. MaterialButton uses the theme’s colorPrimary attribute as its… primary color. That red “cancel” button is very prominent though, let’s change it to gray.

While we could just set the android:textColor on the view directly, we’d still have a red ripple, which we don’t want. Also, we’re unable to change colorPrimary in Theme.Demo because that would affect everything in our app (like “apply”).

Instead, let’s use a theme overlay:

This overlays the ThemeOverlay.Demo.GrayPrimary theme on top of Theme.Demo , for this specific button only. Since we only specified colorPrimary , only this attribute is overridden, and so any usages of colorPrimary for this button (or if it was a view group, any of its descendants) will resolve as gray:

A theme overlay isn’t much different from a regular style/theme. We explicitly set a null parent ( parent=»» ) so that we could be sure that we weren’t accidentally override attributes from any theme ancestors.

The LayoutInflater class will read android:theme and use a ContextThemeWrapper to layer this overlay on top of any ancestor overlays or themes. (See AppCompatViewInflater if using AppCompatActivity or MaterialComponentsViewInflater if using a Material theme).

It’s like an onion with many layers; if a theme attribute is requested, it’ll start from the outside and peel away layers until it finds the target. This is why it’s important to inflate our views with the correct Context —the one closest to the view we’re inflating—otherwise, we might accidentally skip a theme override.

Default styles and theme overlays

When we write views, we can specify a default style resource ( defStyleRes: Int ) which means we don’t have to specify it every time it’s used.

MaterialButton does this. Notice below that we only specify the style for the second instance, because we want to deviate from its default style, which is Widget.MaterialComponents.Button .

We didn’t write MaterialButton , but we can still override the default style because it also specifies a defStyleAttr —a default style theme attribute, which we can set in our theme, and it’ll use this instead of the default style resource:

In our theme, we can define materialButtonStyle and point to a style that we define:

Without any changes in our layout file, we’ve changed the minimum height of a MaterialButton :

So, let’s combine what we learned in this section and the previous one: let’s change colorPrimary for all MaterialButton usages using a theme overlay in the default style:

And… nothing happens!

We can’t use android:theme in a style resource because nothing is looking for it here (it’ll just be ignored). However, we can use materialThemeOverlay instead of android:theme in our style resources:

Hey, this doesn’t work in my custom Views!

This attribute requires explicit support in your custom view because it’s a custom attribute that needs to be handled explicitly.

MaterialButton has support for this attribute. Instead of passing the context directly to the super constructor, it delegates to an internal class in the Material Components library, ThemeEnforcement.createThemedContext(context, . ) .

This function will check for the presence of materialThemeOverlay , then if it’s present and the theme specified is different from the existing one, it’ll wrap the context with ContextThemeWrapper , similar to the way LayoutInflater does.

So… what can I do?

The easiest thing is to copy the function into our project, and use it in the same way, e.g.:

Читайте также:  Как добавить память для андроида

Apart from that, there’s an open issue on the Material Components Android repository to open the class so that we can use this function directly, which could do with some thumbs up.

Let me know if you found this post useful by reaching out on Twitter.

Источник

Android material theme overlay

Android Material Styles and Themes

September 04, 2017

Android platform provides material styles and themes which follow material design guidelines. Material themes were introduced in Android 5.0 (API level 21).

Since material themes are available from API level 21 onwards, apps which use material themes should take care of backward compatibility so that apps using material themes will work on devices running older versions of android.

In this post, I’ll show how to use material styles and themes in your app and provide backward compatibility for material styles.

Material Themes

Android platform provides two material themes, one is dark and second one is light

There are several variants of the above material themes, listed below.

  1. Theme.Material.NoActionBar
  2. Theme.Material.NoActionBar.Fullscreen
  3. Theme.Material.NoActionBar.Overscan
  4. Theme.Material.NoActionBar.TranslucentDecor
  5. Theme.Material.Light.DarkActionBar
  6. Theme.Material.Light.NoActionBar.Fullscreen
  7. Theme.Material.Light.NoActionBar.Overscan
  8. Theme.Material.Light.NoActionBar.TranslucentDecor

Using Material Themes

You can apply material theme to an application or activity by setting theme attribute of application and activity elements in android manifest file. To apply themes to individual views, you can use theme attribute of the views. For more information about themes and styles, you can read Android styles and themes tutorial.

Theme.Material Output

Below is the screen shot of a layout with common UI components and Theme.Material.

Theme.Material.Light Output

Below is the screen shot of a layout with common UI components and Theme.Material.Light.

Material Themes Custom Colors

You can change the theme color for text color, status bar, action bar, navigation bar, window background and UI controls using textColorPrimary, colorPrimaryDark, colorPrimary, navigationBarColor, windowBackground and colorAccent properties respectively.

Material Dialog Themes

Material themes include themes for dialog and overlays. Below is screen shot of dialog window with ThemeOverlay_Material_Dark.

Below are the material dialog and overlay themes and variants of these themes are also available.

  1. Theme_Material_Dialog
  2. Theme_Material_Dialog_Presentation
  3. Theme_Material_Light_Dialog
  4. ThemeOverlay_Material_Dialog
  5. ThemeOverlay_Material_Light
  6. ThemeOverlay_Material_Dark
  7. ThemeOverlay_Material

If you want to change default dialog theme of the material theme applied to application, you can use alertDialogTheme and dialogTheme attribute as shown below.

Material Styles for Text

Below are some of the material text styles and screen shot shows applying the styles to TextView with textAppearance attribute.

  1. TextAppearance.Material.Body1
  2. TextAppearance.Material.Body2
  3. TextAppearance.Material.Inverse
  4. TextAppearance.Material.Small
  5. TextAppearance.Material.Medium
  6. TextAppearance.Material.Large
  7. TextAppearance.Material.Headline
  8. TextAppearance.Material.Title
  9. TextAppearance.Material.Display1
  10. TextAppearance.Material.Display2

Widget Materials Themes

As shown in the above screen shots, default material themes are applied to UI controls when application or activity themes is set to one of the material themes. You can change the color of the widgets as explained above.

If you want particular widgets on a screen to have a different look, you can use theme attribute to apply different themes to it or change specific styling attribute to get required look and feel.

Below screen shot shows two buttons using different styles, Widget.Material.Light.Button and Widget.Material.Button.Borderless.Colored.

Material Themes Compatibility

Since material themes were introduced in Android 5.0, you need to take care of compatibility issue so that application, which is using material themes, run on prior Android versions.

One way to take care of compatibility is to define separate styles for different versions of android and keep them in corresponding res/values folder. This approach is the right choice if you want material design for your app only when it runs on android 5.0 and later versions and non-material themes when it runs on versions prior to Android 5.0. For example, two versions of style file with the same custom theme name is defined and placed in res/values and res/values-21 folders. You can apply the custom theme to application in manifest. Android will pick the style based on its version on the device.

Custom style inheriting material theme that needs to be placed res/values-21 folder.

Custom style inheriting holo theme that needs to be saved in res/values folder.

Using App Compact Material Themes

If you want material themes in all the versions of android, you can use app compact material themes from support library. App compact material themes are material themes which are part of support library and can provide material design for apps running on older android versions.

To use app compact material themes, make sure that app compact library, for example com.android.support:appcompat-v7:26.0.1, is added to your project.

Some of the material themes in support library are Theme.AppCompat.Light, Theme.AppCompat, and Theme.AppCompat.DayNight.

To know app compact styles and themes see app compact styles.

About

Android app development tutorials and web app development tutorials with programming examples and code samples.

Читайте также:  Com android system settings

Источник

Основы темизации в Android

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

Хорошая система дизайна требует правильной настройки стилизации и темизации. Это способствует созданию единообразных и многократно используемых стилей для наших компонентов. Но как на самом деле создать правильную систему стилей и тем?

На этот вопрос нет однозначного ответа, его можно разделить на 5 частей.

Стиль по умолчанию

Стиль в сравнении с темой

Атрибуты

Все начинается с атрибута. Без атрибутов в XML не было бы никаких характеристик, которые бы мы могли определить. Атрибуты — это именованные значения, которые имеют свое определение в файле attrs.xml . Атрибут может быть определен как для представления, так и для темы. Например, атрибут android:layout_width является атрибутом представления, а colorPrimary — атрибутом темы.

Атрибут представления устанавливается в XML представления либо путем установки непосредственно в теге, либо косвенно с помощью style (будет упомянуто позже).. Давайте рассмотрим, как мы можем установить красный фон кнопки с помощью атрибута представления android:backgroundTint .

Примечание: Для доступа к встроенным атрибутам используется префикс android.

Допустим, вы хотите изменить его фон на белый. Вы можете сделать это, установив атрибут android:backgroundTint на белый.

Это хорошо, если вы измените только одну кнопку. Но как быть, если вы хотите изменить все красные кнопки на белые? Этого можно добиться:

Использование атрибута темы для android:backgroundTint

Создание и применение стиля ко всем кнопкам

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

Чтобы использовать атрибут темы для android:backgroundTint , давайте сначала определим пользовательский атрибут темы под названием myButtonBackground в attrs.xml .

Добавление пользовательского атрибута темы:

Тип атрибута задается с помощью поля format . Формат может быть задан как одиночный или множественный тип, например,

android:background format=»reference|color» , который принимает как ссылки на drawable-ресурс («reference»), так и цвет («color»).

Теперь вы можете использовать атрибут myButtonBackground для установки фона вашей кнопки. Но перед этим необходимо задать значение myButtonBackground . Оно должно быть определено либо в теме, либо в наложении темы, которое будет использоваться.

Установка значения атрибута темы:

Затем вы можете использовать этот атрибут для установки фона ваших кнопок.

Установка фона кнопки с помощью пользовательского атрибута:

Если вы измените значение атрибута, то изменится фон всех кнопок, использующих атрибут ?attr/myButtonBackground в качестве фона. В качестве альтернативы можно использовать ?myButtonBackground как сокращение вместо ?attr/myButtonBackground .

Но установка android:backgroundTint на myButtonBackground для всех кнопок может оказаться непосильной задачей. Чтобы решить эту проблему, мы создадим стиль и применим его ко всем кнопкам, используя стиль по умолчанию.

Стиль по умолчанию

Замечали ли вы, что если не задаете кнопке никакого фона, то все равно получаете фоновый drawable (выводимый средствами графических ресурсов объект)? Это происходит потому, что компонент Button (кнопка) имеет стиль по умолчанию, как и любой другой вид. Стиль по умолчанию используется в качестве базового стиля представления.

Давайте проверим стиль кнопки по умолчанию.

Стиль кнопки по умолчанию устанавливается с помощью атрибута темы R.attr.buttonStyle . Это означает, что вы можете изменить стиль по умолчанию всех кнопок в вашем приложении с помощью этого атрибута.

Давайте изменим стиль кнопки по умолчанию в нашей теме так, чтобы фон был красным.

Установка стиля кнопки по умолчанию с помощью атрибута buttonStyle :

Тогда при создании кнопки вы будете получать следующее.

Кнопка с красным фоном

Разве это не напоминает текст с красным фоном? Так происходит потому, что стиль MyButton не наследуется ни от каких стилей. По этой причине все кнопки будут содержать атрибут фонового изображения только в своем стиле по умолчанию. Давайте проверим, как стиль кнопки по умолчанию выглядит в AppCompat .

Стиль кнопок по умолчанию в AppCompat :

Как вы видите, эти атрибуты являются базовым стилем для кнопки. Давайте укажем Widget.AppCompat.Button в качестве родителя стиля MyButton и изменим атрибут background на backgroundTint , поскольку мы хотим изменить только цвет, а не drawable-объект.

Установка родительского стиля кнопки MyButton :

Затем мы получаем кнопку с красным фоном.

Кнопка с красным фоном

Стиль и тема

Мы уже упоминали о стиле и теме, но в чем разница между ними? И стиль, и тема — это набор атрибутов, но разница заключается в том, в каком случае они применяются. Стили предназначены для применения к представлениям, а темы — к действиям или всему приложению. По этой причине стиль должен содержать только атрибуты представления, а тема — только атрибуты темы.

Читайте также:  Low disk space on android

Вы можете изменить стиль представления тремя способами:

Изменение атрибута представления в файле макета

Создание нового стиля и применение его с помощью атрибута представления style в файле макета

Указание стиля по умолчанию

Давайте посмотрим, как можно изменить фон кнопки в файле макета.

Изменение фона кнопки в файле макета:

Теперь давайте проверим, как мы можем создать стиль и применить его к этой кнопке.

Стиль кнопки с пользовательским фоновым drawable:

Установка пользовательского стиля для кнопки:

При применении стиля учитываются только атрибуты представления. Если вы попытаетесь установить любой атрибут темы внутри стиля MyButton , это не сработает. Для наглядности приведем пример:

Использовать атрибут темы colorPrimary внутри drawable фона кнопки.

Изменим значение colorPrimary внутри стиля MyButton

Фоновый drawable, который использует атрибут colorPrimary :

Изменение атрибута темы colorPrimary внутри стиля кнопки:

Тогда, несмотря на то, что мы установили основной цвет как красный, мы получим кнопку с фиолетовым фоном.

Кнопка с фиолетовым фоном

Это происходит потому, что представление знает только о своих собственных атрибутах; Кнопка (Button) не знает об атрибуте colorPrimary, поэтому он игнорируется.

Представление получает свои атрибуты из файла макета или атрибута стиля. Если стиль представления включает атрибут темы, он будет проигнорирован.

Как же тогда изменить атрибуты темы только для одного представления? Здесь на помощь приходит наложение тем.

Наложение тем

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

При применении наложения темы нужно выполнить два шага:

Создайте стиль, состоящий из атрибутов темы, которые необходимо изменить.

Примените этот стиль к файлу макета с помощью android:theme или программно с помощью ContextThemeWrapper .

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

Наложение темы для кнопки:

У наложения темы нет родительского элемента.

Кроме того, лучше начинать именовать стиль с ThemeOverlay , поскольку так его будет легче отличить от других стилей. Эта техника именования используется также в Material Components и AppCompat.

Давайте применим это наложение к кнопке в файле макета.

Применение наложения темы с помощью атрибута android:theme :

Имейте в виду, что если наложение темы применяется к группе представлений, оно также будет применяться ко всем ее потомкам. Другими словами, тема каждого потомка группы представлений накладывается, когда наложение темы применяется к группе представлений.

Применение наложения темы к группе представлений:

Мы также можем осуществить наложение темы программно, обернув контекст представления с помощью ContextThemeWrapper .

Использование ContextThemeWrapper для наложения темы:

ContextThemeWrapper создает новый контекст (оборачивая заданный) своей собственной темой.

TextAppearance

TextAppearance — это класс, который содержит данные только для стилизации атрибутов TextView , связанных с текстом (например, textColor , textSize , но не связанных с видом, таких как maxLines или drawableTop и т.д.).

TextAppearance устанавливается атрибутом android:textAppearance на TextView . Атрибут android:textAppearance работает так же, как и атрибут style . Основное различие заключается в порядке приоритета между ними. style имеет приоритет над android:textAppearance , что означает, что style всегда будет превалировать над общими атрибутами.

Вы можете спросить, зачем он нам нужен, ведь мы можем задать все в style ? Ответ заключается в том, что мы получаем возможность устанавливать только атрибуты, связанные с текстом, и это делает его многократно используемым для всех TextViews , оставляя атрибут style свободным.

Например, давайте создадим внешний вид текста для заголовка.

Использование стиля TextAppearance.StylesNThemes.Header в качестве оформления внешнего вида текста:

Как видите, атрибут style для TextView является свободным и может использоваться для настройки других атрибутов представления. Вы также можете установить android:textAppearance , создав стиль.

Давайте создадим стиль однострочного заголовка.

Однострочный стиль заголовка:

Теперь вы можете установить этот стиль с помощью атрибута style и повторно использовать его для любого текста.

Применение однострочного стиля заголовка к текстовому представлению:

Если вы хотите более глубоко погрузиться в изучение темы внешнего вида текста и приоритета стилей, я настоятельно рекомендую вам прочитать эту статью.

Заключение

Атрибуты являются ключевым понятием в стилизации и темизации. Используйте атрибуты представления для их стиля и атрибуты темы для приложения, Активности или иерархии представлений. Если вы хотите изменить стиль для всех инстансов данного типа представления во всем приложении, вам подойдут стили по умолчанию. Наложения тем используются для переопределения атрибутов темы, и вы можете использовать их даже для представлений в заданной иерархии. Внешний вид текста может помочь вам сформировать текстовые атрибуты TextViews с помощью android: textAppearance , оставляя атрибут style свободным.

Android-разработчиков с опытом от 3 лет и всех желающих приглашаем на онлайн-интенсив «Полный coverage. Покрываем Android-приложение юнит/интеграционными/UI тестами».
На интенсиве мы:
— Научимся покрывать android приложение юнит/интеграционными/UI тестами.
— Рассмотрим различные кейсы: покрытие тестами suspend функций, RX цепочек.
— Изучим популярные инструменты для написания тестов.
— Обсудим best practices по покрытию тестами.

Источник

Оцените статью