Monday 8 March 2010

Order precedence in styling

Android calculates the effective style of a widget by merging the individual style definitions from multiple sources (viz., view definition, styles.xml, theme and Android defaults) using the following order precedence:

  1. Widget's inline attributes, which override the ...
  2. styles in the styles.xml file, which override the ...
  3. default styles of the widget, which override the ...
  4. override the styles specified in a theme

This order precedurce rule is evaluated on a "per attribute" basis. For ex:- the textColor specified in a style is overridden by textColor attribute specified "inline" on the widget (similar to CSS).

Let's see it action

Source # 1: Styles in the "styles.xml" file

"Styles.xml" file contains zero or more styles in it. A style is identified by it's name, and is a collection of zero or more widget attributes (viz., textColor, background color etc). A style has no knowledge of where it will be used. This is unlike CSS, which has a concept of selectors. A style is attached to a widget in a view definition XML file or in code.

We will use the following "styles.xml" file to experiment with the order precedence rules:

  1. <resources>
    1. <style name="DesiredApplicationTheme">
      1. <item name="android:typeface">monospace</item>
      2. <item name="android:textSize">20px</item>
      3. <item name="android:textColor">#993333</item>
      4. <item name="android:textStyle">normal</item>
      5. <item name="android:background">#C3C3C3</item>
    2. </style>
    3. <style name="MediumFontActivityTheme" parent="DesiredApplicationTheme">
      1. <item name="android:textSize">30px</item>
    4. </style>
    5. <style name="LargeFontActivityTheme"><
      1. <item name="android:textSize">40px</item>
    6. </style>
    7. <style name="BrightYellow" >
      1. <item name="android:textColor">#FFFF66</item>
      2. <item name="android:background">#FF3399</item>
    8. </style>
    9. <style name="SoftYellow" parent="BrightYellow">
      1. <item name="android:textColor">#FFFFCC</item>
    10. </style>
  2. </resources>
Source # 2: Themes in ApplicationManifest.xml"

A theme is a special kind of style that affects the look and feel of an entire applicatin on activity. The definition of the theme (which is a style) is defined in the styles.xml file, but is applied to an activity or application in the "ApplicationManifest.xml" file.

We will use the following "ApplicationManifest.xml" file to experiment with the order precedence rules. These there actvities will paint the same view./p>

  1. <application android:theme="@style/DesiredApplicationTheme" android:icon="@drawable/icon" android:label="@string/app_name">
    1. <activity android:name=".SmallFontActivity"/>
    2. <activity android:name=".MediumFontAcvitity" android:theme="@style/MediumFontActivityTheme"/>
    3. <activity android:name=".LargeFontActitiy" android:theme="@style/LargeFontActivityTheme"/>
    4. </application>
Source # 3: Widget attributes in view definition XML

A widget's look and feel can be manipulated using it's attributes (ex: android:textColor) in a view layout definition file (or in code).

We will use the following view definition file to experiment with the order precedence rules. This view will be painted by all the activities defined above:

  1. <TextView id="@+id/TextView01" android:text="Style Me." android:layout_width="fill_parent" android:layout_height="wrap_content"/>
  2. <TextView id="@+id/TextView02" android:text="Style Me." style="@style/BrightYellow" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
  3. <TextView id="@+id/TextView03" android:text="Style Me." style="@style/SoftYellow" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
  4. <TextView id="@+id/TextView04" android:text="Style Me." style="@style/SoftYellow" android:textStyle="italic" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
Order precendence effect
When the SmallFontActivity is launched:

This activity does not define a theme of its own. It inherits the application's theme. The effective style for each text view is calculated as follows:

TextView01
  • The text color, #993333, is from DesiredApplicationTheme
  • The background color, #C3C3C3, is from DesiredApplicationTheme
  • The textStyle, "normal", is from DesiredApplicationTheme
  • The font size is 20px from DesiredApplicationTheme
  • The font family, monospace, i sfrom DesiredApplicationTheme

DesiredApplicationTheme is attached to the application in the "ApplicationManifest.xml"

TextView02
  • The text color, #FFFF66, defined in BrightYellow overrides the application's text color, #993333, defined in DesiredApplicationTheme
  • The background color, ##FF3399, defined in BrightYellow overrides the application's background color, #C3C3C3, defined in DesiredApplicationTheme
  • The textStyle is application's default, "normal" , defined in DesiredApplicationTheme
  • The font size is applicaiton's default, 20px, defined in DesiredApplicationTheme
  • The font family is application's default, monospace, defined in DesiredApplicationTheme
TextView03
  • The text color, #FFFFCC, defined in SoftYellow overrides the text color, #FFFF66, defined in BrightYellow which in turn overrides the application's text color #993333, defined in DesiredApplicationTheme
  • The background color, #FF3399, is from BrightYellow style (SoftYellow extends BrightYellow), which overrides the application's background color, #C3C3C3, defined in DesiredApplicationTheme
  • li>The textStyle is application's default, "normal" , defined in DesiredApplicationTheme
  • The font size is applicaiton's default, 20px, defined in DesiredApplicationTheme
  • The font family is application's default, monospace, defined in DesiredApplicationTheme
TextView04
  • The text color, #FFFFCC, defined in SoftYellow overrides the text color, #FFFF66, defined in BrightYellow which in turn overrides the application's text color #993333, defined in DesiredApplicationTheme
  • The textStyle defined inline, italic, overrides the appication's default textSytle, normal, defined in DesiredApplicationTheme
  • The background color, #FF3399, is from BrightYellow style (SoftYellow extends BrightYellow), which overrides the application's background color, #C3C3C3, defined in DesiredApplicationTheme
  • The font size is applicaiton's default, 20px, defined in DesiredApplicationTheme
  • The font family is application's default, monospace, defined in DesiredApplicationTheme
When the MediumFontActivity is launched:

This activity uses the MediumFontActivityTheme. In the "styles.xml" MediumFontActivityTheme extends the DesiredApplicationTheme styles. It retains all the properties of DesiredApplicationTheme and only overrides font size.

The order precedence rule analysis will be similar to our previous analysis except that for this fact:

TextView01-04
  • The font size of 30px defined in MediumFontActivityTheme overrides the font size 20px from DesiredApplicationTheme
When the LargeFontActivity is launched:

This activity uses the LargeFontActivityTheme. In the "styles.xml" LargeFontActivityTheme does not extend the DesiredApplicationTheme style, hence it overides all the properties of DesiredApplicationTheme and retains none.

The effective styles for each text view is now calculated as follows:

TextView01
  • The text color is default system color becuase the LargeFontActivityTheme does not specify it nor inherit it
  • The background color is default background color becuase the LargeFontActivityTheme does not specify it nor inherit it
  • textStyle is default style becuase the LargeFontActivityTheme does not specify it nor inherit it
  • The font size is 40px from LargeFontActivityTheme that was attached to the activity in the ApplicationManifest.xml
  • The font family is default familty from becuase the LargeFontActivityTheme does not specify it nor inherit it
TextView02
  • The text color of #FFFF66 defined in BrightYellow overrides the default text color
  • The background color is #FF3399 defined in BrightYellow overrides the default background color
  • textStyle is unaffected, which the default textStyle
  • The font size is 40px is unaffected, and is from LargeFontActivityTheme
  • The font family is unaffected, which is the default family
TextView03
  • The text color of #FFFFCC defined in SoftYellow overrides the text color, #FFFF66, defined in BrightYellow overrides the default text color
  • The background color is #FF3399 is unaffected, and is from BrightYellow style
  • textStyle is unaffected, which the default textStyle
  • The font size is 40px is unaffected, and is from LargeFontActivityTheme
  • The font family is unaffected, which is the default family
TextView04
  • The text color of #FFFFCC defined in SoftYellow overrides the text color, #FFFF66, defined in BrightYellow overrides the default text color
  • textStyle is italic defined inline overrides the default textStyle
  • The background color #FF3399 is unaffected, and is from BrightYellow style
  • The font size is 40px is unaffected, and is from LargeFontActivityTheme
  • The font family is unaffected, which is the default family
Source # 4: The default styles

Default styles are the ones provided by Android on a per widget basis. They have higher precedence than themes, which is quite interesting. To see this source kick in order precedence evaluation, let us replace the TextViews in our view with Buttons (Button inherits from TextView) and launch the SmallFontActivity actvity.

TextViewButton

TextView01 and Button01 have no inline style attributes nor style attribute specifind on them. Hence, it is upto either the theme or the Android's widget default to provide the styling.

The theme suggests the textColor should be #993333. It makes it to the TextView, but not to the Button. This is becuase the widget defaults have a higher precedence over theme, and the button default text color is black.

In contrast, Button02-04 which either have the style attribute or inline style attributes specified, look exactly like their TextView counterparts and very different than Button01 with its default look and feel. This is becuase, the style attribute and inline style attribute higher precedence than widget defaults.

No comments:

Post a Comment

Blog Archive

Followers