This may not come as a shock to you, but the most important variable in a mobile app's success is its design. Developers work hard to apply pixel-perfect designs so that users will spend time using that app and not any other. The rules and guidelines of how to design the best apps are there, but history shows us that they do change. Experience with themes and styles is crucial for Android developers. Especially in a world in which UI/UX is more important than anything.
At I/0'16, Android Studio 2.2 Preview 1 released with a re-written layout designer. Along with the material design concept revealed two years ago, this is a good sign that Google sees the importance of design and aims to support developers by giving them the tools they need to implement them well.
This post is meant to be an introduction to the concepts of themes and styles, to help you on your journey towards pixel-perfect Android apps.
Theme vs Style
When applying a design to your app you need to work smart. As long as you are working with competent designers, you'll find that most of the screens share the same design components such as buttons, textviews etc.
Obvious lesson: Applying the same properties each time for every component is not good practice. If you define properties of common components once it will be better and more robust to design changes. So we need to use Style and Theme. Style is a collection of properties for a View, Theme, on the other hand, is a style for an Application or an Activity. If you need to, you can also apply a Theme to components, but we'll get to that later.
Let's start with Theme 101. We begin by defining a theme for our app
Our theme should always have a parent. Parent themes are pre-defined, and you can try a few out and select one you like. I usually choose "Theme.AppCompat.Light.NoActionBar". It supports the material design guidelines and is also backwards compatible. Below, you will see the core items of a material theme. You should pick and choose from these according to your app's design.
Now that we've defined our theme, let's look at how we can apply it to our app.
We define the attributes of our application and activities in the 'AndroidManifest.xml'. Our Theme is one of these attributes. When we apply a theme to our application, all activities in the application will be applied with that theme. We don't need to apply a theme to activities separately. We add the theme attribute to the application tag like this
There are lots of attributes in a theme you can override, but some of them are very important at least for me. They are "colorPrimary", "colorPrimaryDark", "windowBackground" and "textColorPrimary". You want to play with these to fit your designs.
All done! Satisfied with our theme, we start coding. However, while we are implementing UIs, we come across a screen that has some visual differences with other screens. For example the toolbar title and window background is different, so what do we do now? Do we need a new theme? Yes. So we will define a new theme and set all attributes again? No.
We will use the theme we defined before and we will override only the differences. We will set parent theme of our new theme to previous theme. We have two options right now. These are:
Above you can see the themes "AppThemeLight" and "AppTheme.Light", they are exactly the same themes but their definitions are different. I prefer "AppTheme.Light", because the naming is more sensible, it is also easier to track by someone else in the project. You can override this theme as well. For example just say: "AppTheme.Light.RedBackground".
Now all we have to do is apply this new theme to an individual activity and this activity theme will be different than the app's default theme.
That's pretty much it for Themes! Let's move on to Styles.
We've created a theme for our app, but now we need to specify attributes for common views like textviews, edittext's or buttons. That's why we define styles. For example, while looking at the designs, you realized that for two buttons, the button text sizes are same but there are two different button functions with different background colors. One of them is an "OK" button and the other one is a "Cancel" button. Let's define a style for that case.
Here we first created a base style called "Button", its parent is from the existing styles, so we don't need to define everything, we change only what we want. We set the textsize and textcolor in the base style. After that we defined two new styles named Button.Ok and Button.Cancel, and added background parameter to each of them. Now let's look at how to apply these styles to our buttons.
android:style="@style/Button.Cancel" this line adds the style to our view and here is the result:
Next, during the implementation, you notice that the designer used the same button with a different text size like 18sp for some reason (he doesn't seem to be the best designer in the world, but hey, we need to play with the cards we are dealt). We have two choices here. If this anomaly happens only once, you can override your style like this:
This way, you don't need to define every attribute again, you can just override the needed attribute and that's it.
However, if this 18sp text on buttons crops up more than once, then it's better to define a new style like extending 'Button.Ok' to 'Button.Ok.18' and defining the new text size under that style.
Now let's say that, again for some reason, a design request came to change all Ok buttons' background colors from green to yellow (the designer is going mad here). It is pretty easy for us to do that because we defined a style for all "ok" buttons, so we only need to change the style to fulfill the request.
Here we changed the background color of the Button.OK style to yellow and that's it. All Ok buttons have yellow background now. If we hadn't defined a style, we would need to change the background color of every ok button in the project.
Themes and styles give us the opportunity to reuse code while developing UIs. Especially during the early stages of a project, you will find that the designs of an app always undergo these small changes, whether it's a small color change or a rehaul of button styles. Defining themes and styles looks trivial in the beginning, but whenever things become more complicated, the importance of these are more obvious than ever. It not only saves time when making changes in UI, but also allows us to create a more organized and sustainable codebase.