The Right Way
In android, the UI layer is mainly built using XML layouts. In those XML layouts we can use a variety of resources to control the look and feel of the User Interface. It is possible to add Inline configurations and styling directly to a “VIEW” in the layout, but it is strongly discouraged.
A perfect way to abstract your UI is to have your strings, dimensions and styles declared separately. These are stored as resources and referenced in your view.
The visible elements in your app, for example buttons, will likely be consistent in terms of the look and feel. This is where creating a button style would come in handy.
This same example applies to multiple other views such as TextViews and even EditTexts. After creating styles for specific views you can apply these styles explicitly. This can be annoying if you need to remember to add a style to every view that you created.
This is where Themes come to the rescue!
Consider Themes in android as a bundle of styles that we apply to our application or to a specific activity. With the AppCompat library you can also specify a theme to View or ViewGroup. Thanks to the AppCompat library, material styled themes can be utilised for older versions of Android as well.
So what goes in the Theme usually?
Anything that the base theme supports can be added in your theme. You can find out what your theme supports by going through the source code of BaseTheme. Then checking out all the styles and colors that you can specify.
When you apply a theme to an application or activity, all sub elements will receive that style. You can override the theme style by explicitly specifying in it the layout.
Inheritance in themes is pretty useful for you to customise a theme, simply by extending it and then overriding the attributes that you want to customize.
Inheritance with views can be achieved in 2 different ways:
- Explicit Inheritance adding a parent attribute to the style tag:
<style name="MotherTheme" parent="Theme.AppCompat.Light.NoActionBar">
- Implicit Inheritance, by prefixing your theme with [ParentTheme].[YourTheme]
Explicit Inheritance will always override Implicit Inheritance.
Another thing about inheritance, and that you are encouraged to use, is something that I call the Diamond Inheritance. This is basically used to support multiple themes that have different attributes to be configured for a certain base theme.
I guess the above diagram is self explanatory of what diamond inheritance is.
Most developers are currently used to adding specific SP values in dimensions file and maybe creating a text style that would be added to a specific TextView. If we have multiple text styles specified by our designer that would end up with us creating many numbers of custom made text styles from scratch.
What if there is a way for you not to do that at all!!
The only prerequisite of this would be that you would use one of the predefined text appearance style in the Material Design Standard. Basically following the Android Design spec as your base.
The above image contains all the predefined styles in the Android SDK that we can simply use.
<TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.AppCompat.Headline" />
Keep them as minimal as possible! Do not specify dimensions of every special case that you have or per feature. Keep your dimensions as generic as possible to be re-used. One example would be to call most of your dimensions “spacings” rather than margins or paddings. Spacings can be used for both margins and paddings that need to be specified to a view.
One example of dimensions values that I regularly use is :
<!-- Global --> <dimen name="spacing_huge">48dp</dimen> <dimen name="spacing_xlarge">32dp</dimen> <dimen name="spacing_large">24dp</dimen> <dimen name="spacing_normal">16dp</dimen> <dimen name="spacing_small">8dp</dimen> <dimen name="spacing_micro">4dp</dimen>
So other than the theme attributes that we can customise and configure. We can also add custom theme attributes that we can define and use throughout our application. The main reason for this is to have all styles linked to the theme. Rather than creating a style that is not linked to the theme at all.
Example of how to create those custom attributes in your theme is :
Basically overlays are themes that don’t extend any super theme but rather override certain attributes of the current theme applied to a view, activity or application.
There are 2 types of overlays, Light and Dark. The main use-case that overlays are used for is for Toolbars, since usually a toolbar has an opposite theme of your current app (Dark background with light color for a light themed app).
Image courtesy of Family O’Abe