Leave a rating/review
When it comes to styling your Android apps, you’re not just limited to one approach. You’re provided with different options.
- You can set the attributes directly in the layout or using the attributes panel.
You did this for the target text where you changed the text size.
- You can set attributes of views programmatically inside the activity.
You did this in a challenge from the previous course when you temporarily set the height of the hit me button.
Now, these approaches are not really scalable and may not be ideal for every scenario. Imagine you want a button or textview to have the same design. If you used the first approach of setting attributes directly, you’ll end up copying and pasting xml attributes.
Now think about what would happen if you had 10 buttons that uses the same design in your app: I know you already smell it, right? That’s a code smell because changing one attribute would require us to change it in 10 different places.
- For this type of scenario, you create a style for the button.
A style is simply a collection of attributes that specifies the design for a single View. You group these attributes together in a file that android studio provides. Then you can apply the style to a View just like the button. With this, whenever you change an attribute in the style definition, all views that uses that specific style gets updated.
Now a style focuses on a View. What if we want to style our entire app or activity, what do we use?
Well, we use a theme to do that. A theme is basically a collection of attributes that is grouped together and applied to an entire app or activity. You can also apply it to a parent view and the children could take up the styling specified in the top hierarchy of the view.
Themes and styles are similar but are very different as you’ll see when we get to the demo. Styles and themes are designed to work together to design the appearance of your app. They offer the benefit of separation of concern because the file for the appearance of your app is declared in a different file which is separate from your code logic and layout structure.
To access the theme used in your project, go ahead and open up the AndroidManifest.xml file.
If you look at the application node, you can see it has an attribute named android:theme.
Here it says the theme is Theme.Bullseye.
Remember, themes are declared using the style syntax inside the same file and that’s why you have style in its path.
You can also add a theme for an activity too by creating a theme for it and assigning it to the android:theme property.
Now, to open up the theme file, hold down the Cmd key and then click on it.
A context menu pops up showing you multiple implementations of the theme.
If you look closely at the options, you will see that we have two bullseye themes:
one normal theme known as light theme and the other for night mode otherwise known as dark mode on your Android devices.
Click on the first one which is the light theme.
This opens up the theme.xml file which contains the light theme.
You can see that the theme is declared using a style tag.
The style tag has a name and parent property.
When working with themes, you always have to extend a predefined theme provided by android as the parent.
This is because the parent theme contains all the necessary attributes for different views and elements.
Our theme here just overrides and supplies the core information that all dependent views and elements would use.
When I mention element, what I simply mean here is non-view elements like the status bar.
Go ahead and run the app.
The status bar is not part of our app but its uses a purple color which is gotten from our theme. That is one difference between a theme and a style. A theme can affect the appearance of non-view elements like the status bar.
Now the statusBarColor makes use of the colorPrimaryVariant.
But what exactly is the colorPrimaryVariant?
If you look above, you can see we have different color property declarations. We have the primary and secondary brand color. And beside them we have tiny previews for individual colors. You declare easy to use names for android resources for example colors, so that you can easily refer to them later. And by the way, this is how comments look in an xml file. It is quite different from how comments are indentified in kotlin code.
Okay, looking at our app, you can see the views already makes use of the colors from this theme.
The buttons makes use of the colorPrimaryVariant.
The seekbar makes use of the colorSecondaryVariant.
The parent theme we’re using understands these names declared in the theme.
So when we change it here, it affects all views that use those names in our app.
You can see that something like purple_500 isnt very descriptive.
With themes, you can provide a semantic name for that color resource just like what is done in here.
To view the actual color resource, as always, hold down the Cmd key then click on one of them.
This opens up the colors.xml resource file.
You can see all the colors used in the application.
You will use a different color pallette for the Bullseye app.
But before we do that, let’s see what our app would look like in dark mode. Open up the layout file.
Then up in layout editor’s toolbar, click on the night mode button. Then select Night. The layout instantly updates to show you what the UI would look like when dark mode is enabled on the device. Remember you have two themes: one for light mode and the other for night mode. When you change your device setting to night mode, android uses the night theme. You can go ahead and open up the night theme and monitor the values.
Okay, I’ll change that back to Not-Night mode.
Then head back to the colors.xml file.
And replace the colors with the following set of colors:
<color name="red_accent">#FF5252</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="grey">#808080</color>
And you can see the previews by the left.
Okay, head back to themes.xml file.
You can see that android studio complains and this is simply because the color names it uses doesnt exist anymore.
I’ll remove the secondary brand color section and update the primary color and primary variant to the following:
<item name="colorPrimary">@color/red_accent</item>
<item name="colorPrimaryVariant">@color/red_accent</item>
I’ll also update the night theme. Open up the night theme file. Remove the secondary brand section.
Then make the following update:
<item name="colorPrimary">@color/red_accent</item>
<item name="colorPrimaryVariant">@color/black</item>
<item name="colorOnPrimary">@color/white</item>
Run your app. And you can see it updates accordingly. You can go to the layout file and check what it looks like in night mode.
Finally let’s hide the status bar to make bullseye a fullscreen app. You will be achieving this using themes. Head over to the main activity file. Remove the code you added earlier that hides the action bar.
Run your app. And you can see that the action bar reappears.
Head back to the themes.xml file.
You will create a new theme for the main activity that will make it a full screen activity.
Paste in the following code below the current theme.
<style name="Theme.Bullseye.NoActionBar.FullScreen" parent="@style/Theme.Bullseye">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>
</style>
You can give it any name but I’m following the naming convention used by default themes provided by android. Here, by looking its name, you can see that it is a fullscreen theme without an action bar. The items in this theme are self descriptive. It also extends a parent theme so that it can retain existing styling. In this case the parent theme is the base application theme.
Alright, let’s set the main activity to use this theme.
Head over to the AndroidManifest.xml file.
Add the following property to the main activity tag:
...
android:theme="@style/Theme.Bullseye.NoActionBar.FullScreen"
...
Run your app.
And there you have it. The main activity is now full screen with both the action and status bar hidden.
Let’s work with creating styles in the next episode.