Introduction to android styles and themes part II

download
INTRODUCTION TO ANDROID STYLES AND
THEMES PART II
In the first part of this series, we covered:
What are styles and themes and their difference
How a programmer can create a style
Inheritance
In this post we shall cover:
Inheritance of system styles
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;

 

screen shot with Theme.Black

 

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 elements
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
Theme.Green

 

Theme.Blue
Theme.Red
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.