INTRODUCTION TO ANDROID STYLES AND
THEMES PART II
In the first part of this series, we covered:
1.
What are styles and themes and their difference
2.
How a programmer can create a style
3.
Inheritance
In this post we shall cover:
1.
Inheritance of system styles
2.
Themes
INHERITANCE OF
SYSTEM STYLES
Inheriting system styles in android works no differently
from inheriting custom styles. You only have to change the way you communicate
the parent-child relationship to android.
While inheriting custom styles, we used the notation
parentStyle.childStyle
Here,
childStyle
will use all
attributes of parentStyle
and can define its own as
well to override parentStyle
’s attributes.
Then you’d reference the
childStyle
with the whole notation in your layouts like so:style=”@style/parentStyle.childStyle”
NB. In case you have another child style you want to inherit
all styles available to
childStyle
, and may be adds a
new attribute, just go ahead and create a new style and call it
parentStyle.childStyle.secondChildStyle
and then
reference it from your layouts like so:
style=”@style/parentStyle.childStyle.secondChildStyle”
With this pattern, you can append as many styles as you like.
In the case of system styles, you need to add an extra
attribute to your
style
element.
Let’s dive right into the example and ensure we make our
Button and TextView explicitly inherit from the parent Button and TextView
styles.
Actually itis best practice that everytime you are creating a custom
style for a view, first inherit all attributes of the parent style in the
system and then go ahead and add your own attributes.
Now change your
styles.xml
to look
like so:
styles.xml
xml version="1.0"
encoding="utf-8"?>
<resources>
<style
name="myButton"
parent="@android:style/Widget.Button">//inheriting from default button style
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style
name="myTextView"
parent="@android:style/Widget.TextView">//inheriting from default textview style
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#FFFF00</item>
</style>
<style
name="myButton.myButtonRedText">
<item name="android:textColor">#FF0000</item>
</style>
<style
name="myTextView.myTextViewBlue">
<item name="android:textColor">#0000ff</item>
</style>
At this point we have not changed anything about how our app
looks.
Why?
Because we have just explicitly done what android has been
doing implicitly (by default). I.e. android has been inheriting all default styles
for our Buttons and TextViews and simply
taking our explicitly defined attributes as overrides.
Now you have mastered how to inherit styles attributes from
custom styles and default system styles.
Next we are going to look at android themes.
THEMES
As defined in part I of this series, a theme is a set of
styles which determine the visual representation of your app (how your app
looks). I believe the idea is now clearer, since we have just covered styles.
In essence, a theme is no different from a style. A theme is
only a set of styles grouped under one parent (the theme).
·
A style and theme are both defined in
values/*.xml files with root element
resources
·
The child element of root i.e.
style
works for both styles and themes. The
name
attribute references either the theme name or the
style name. likewise the parent
attribute references a
theme or a style any of them is inheriting from. Only that of course, a theme
inherits from another theme and a style, from another style.
·
The
item
element
references an attribute for both. For a theme, each item element references the
name
of style resource and for a style, each item
element references the name
of an attribute.
It will help a lot to familiarize yourself with this themes.xml
file, it’s the android default theme for API level 10 and lower. And this styles.xml file which defines the global theme styles of android.
How to apply system theme
to your application or activity
Unlike a
style
whose scope is
limited to a single view, the scope of a theme spans a whole
activity
or application
.
We ended part I of this series when our app had a dark theme
remember?, like so;
Notice the dark background (
Theme.Black
.), for my API level of 8, it’s the default.
When you look into the Themes.xml
file, you should see several themes which all inherit
Theme
e.g.
Theme.Light.NoTitleBar
etc. Your task is just to
familiarize yourself with the themes available for your target API level since
each new API level almost ships with new themes. You can actually tell your app
to detect the API level and apply a theme accordingly. That is a topic for
another post.
Let’s experiment with applying
Theme.Light
. Just go to your manifest file and add this attribute to the
Application
element and of course you now know that
you can as well choose to apply it to a specific
activity
element.android:theme=”@android:style/Theme.Light”
Now reload your app and it should look like so:
![]() |
screen shot with Theme.Light |
xml version="1.0"
encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.simplejavan.theme"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8"
/>
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.Light">//invoking the theme
<activity android:name=".ThemeAndStyleActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"
/>
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
</manifest>
Creating a custom
theme
Now that we know how to explicitly tell our app to use a
specific theme, we are going to create our own theme and make it first inherit
from
Theme.Light
. This will help us understand:
1.
How to create custom themes
2.
How to inherit styles of a system them
3.
How to apply custom themes to activity or
application
Navigate to the
res/values
directory in our ThemeAndStyle
project created in part I of this series. Right click and go to New->android
xml. And call it themes.
Alternatively, click on the
res/values
directory and select the android xml icon in your IDE toolbar.
We are going to create 3 separate themes to nail down the
idea, however all of them are defined in the same file. Here is the content of themes.xml
xml version="1.0"
encoding="utf-8"?>
<resources>
<style name="Theme.Red"
parent="android:style/Theme.Light">
<item name="android:buttonStyle">@style/redTheme.Button</item>
<item name="android:textViewStyle">@style/redTheme.TextView</item>
</style>
<style name="Theme.Green"
parent="android:style/Theme.Light.NoTitleBar">
<item name="android:buttonStyle">@style/greenTheme.Button</item>
<item name="android:textViewStyle">@style/greenTheme.TextView</item>
</style>
<style name="Theme.Blue"
parent="android:style/Theme.Light">
<item name="android:buttonStyle">@style/blueTheme.Button</item>
<item name="android:textViewStyle">@style/blueTheme.TextView</item>
</style>
</resources>
Ignore the dot notation I have used in naming the themes,
they really don’t inherit from any custom theme, but are rather used for
clarity since we are creating 3 different basic themes.
Notice the inheritance pattern involving the
android namespace
and the
parent
attribute.
We are inheriting from
Theme.Light
.
Notice the little tweak we have added to Theme.Green
.
Theme.Light.NoTitleBar
is another
system theme that inherits from Theme.Light
and just
adds a single property i.e. hides the title bar.
Each
item element
under a theme
definition represents a whole style definition, contrary to the styles where an
item element
represents a single attribute. The style
names you are seing in the item element
’s are the
system names referencing styles for the corresponding views (Button and
TextView). You must have noticed that if you took a look at the system themes.xml. The philosophy is simple,
we are inheriting a system theme, so each item element
gives us an opportunity to override an existing style in the system theme,
similar to styles.xml, where we
inherit a system style applying to a view and then in each item
element
, we override a given attribute.
Now the values of our
item element
s
are references to styles we have to define. As you can see, we shall define
style attributes for each view under each theme. Interesting right???
To avoid confusion and the extra step of editing the main.xml to change style reference
names, create a second
styles
xml file and call it styles2.xml, below is the content.
xml version="1.0"
encoding="utf-8"?>
<resources>
<style name="greenTheme.Button"
parent="@android:style/Widget.Button">
<item name="android:textColor">#00ff00</item>
</style>
<style name="greenTheme.TextView"
parent="@android:style/Widget.TextView">
<item name="android:textColor">#00ff00</item>
</style>
<style name="redTheme.Button"
parent="@android:style/Widget.Button">
<item name="android:textColor">#ff0000</item>
</style>
<style name="redTheme.TextView"
parent="@android:style/Widget.TextView">
<item name="android:textColor">#ff0000</item>
</style>
<style name="blueTheme.Button"
parent="@android:style/Widget.Button">
<item name="android:textColor">#0000ff</item>
</style>
<style name="blueTheme.TextView"
parent="@android:style/Widget.TextView">
<item name="android:textColor">#0000ff</item>
</style>
</resources>
Ignore the dot notation naming of the styles, I am not
inheriting any custom styles here, it’s just any ordinary string but I wanted the style names to be clear
since I have created 3 separate styles corresponding to each theme above.
For the sake of being neat, open our original styles.xml, remove the extra child
style definitions as well as any color style attributes. Let us leave this
style file strictly for layout attributes such as
layout_width
and
layout_height
. Remove also the inheritance and just
leave it as an isolated style definition.
Now our styles.xml looks like so:
xml version="1.0"
encoding="utf-8"?>
<resources>
<style name="myButton">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="myTextView">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
</resources>
Our theme is now ready for referencing. This is where we
shall see how to apply a custom theme to an
Application
or Activity
.
For the case of a custom theme, we eliminate the
android namespace
and just reference the theme using a
style reference like so:
xml version="1.0"
encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.simplejavan.theme"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8"
/>
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/Theme.Red">
<activity android:name=".ThemeAndStyleActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"
/>
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
</manifest>
In this code, we have referenced
Theme.Red
, you can go ahead and test with
Theme.Green
and Theme.Blue
.
Below are my screen shots
I believe you now have a firm understanding of inheriting system styles, how themes are
created and applied.
In part III and the last part of this series, we are going
to look at switching themes programmatically and then see how to use simple and
complex colors to give a powerful visual to our user interface.
No comments:
Post a Comment