Titanium 3.X
Alloy Styles and Themes

Alloy Styles and Themes

Titanium Style Sheets

The Titanium Style Sheets (TSS) file uses a JSON-like syntax to define the attributes of elements in the XML files. All TSS attributes are the properties of the Titanium object. For examples, when defining the style for a Button object, each property, such as backgroundDisabledColor, backgroundFocusedColor, backgroundSelectedColor, etc., can be specified as an attribute in the TSS file.

Styles are defined at three different levels: markup element, class attribute and the id attribute. When mixed together, the id attribute overrides both the class attribute and markup element, and the class attribute overrides the markup element.

In the TSS file, define attributes as key-value pairs, where the key is the name of the markup element, the class name prefixed with a period (.), or the id name prefixed with a hash tag (#) and the value is a dictionary of attributes (or Titanium class properties) to set. You can optionally place a conditional block with the key name to apply styles under certain conditions as explained in the Platform-Specific Styles and Custom Query Styles sections below.

You can use the following values and operators in your TSS file:

  • JSON values, that is, Strings, Numbers, Objects, Array, Booleans and null

  • Titanium SDK constants, for example, Ti.UI.SIZE

  • Localization functions, either Ti.Locale.getString() and its shorthand L()

  • Variables from the Alloy.CFG or Alloy.Globals namespaces

  • Bitwise operators, which includes bit shifting ('>>', '<<', and '>>>'), bitwise AND ('&'), bitwise OR ('|') and bitwise XOR ('^')

You may also place single (//comment) and multiline comments (/* comment */) in your TSS files unlike regular JSON files.

Alloy does not support the CSS concept of child or descendent selectors, that is, specifying and applying styles based on the tag hierarchy.

The following code defines a style sheet (index.tss):

app/styles/index.tss
// This is applied to any element with the class attribute assigned to "container" 
".container": {
        backgroundColor:"white"
},
// This is applied to all Labels in the view
"Label": {
    width: Ti.UI.SIZE,
    height: Ti.UI.SIZE,
    color: "#000", // black
    transform: Alloy.Globals.rotateLeft // value is defined in the alloy.js file      
}, 
// This is only applied to an element with the id attribute assigned to "label"
"#label": {
    color: "#999" /* gray */
}

which pairs to this view markup (index.xml):

app/views/index.xml
<Alloy>
    <Window class="container">
        <Label id="label" onClick="doClick">Hello, World</Label>
    </Window>
</Alloy>

In the example code above, the Label object in the view inherits styles from both 'Label' and '#label'. Since '#label' is defined at the id level, the color of the label will be gray ('#999') instead of black ('#000'). For the Label's transform property, the TSS file is using a function assigned to the Alloy.Globals namespace defined in the initializer file:

app/alloy.js
Alloy.Globals.rotateLeft = Ti.UI.create2DMatrix().rotate(-90);

Global Styles

You can create a global style file, called app.tss, which applies all styles defined inside it to all views, but does not override the non-global styles or property attributes in the markup. For example, suppose you have the following three files in your project:

styles/app.tss
"Window":{
    backgroundColor: 'white',
    layout: 'vertical'
}
"Label":{
    color: 'gray',
    textAlign: Ti.UI.TEXT_ALIGNMENT_LEFT,
    backgroundColor: 'transparent',
    font: {
        fontFamily:'Helvetica',
        fontSize: '12dp',
        fontStyle: 'normal',
        fontWeight: 'normal'
    }	
}
styles/index.tss
"Window":{
    backgroundColor: 'blue'
}
"Label":{
    top: 20,
    left: '25dp',
    right: '25dp'
}
"#subtitle":{
    width: Ti.UI.FILL,
    textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER,
    font: {
        fontSize: '16dp',
        fontWeight: 'bold'
    }		
} 
views/index.xml
<Alloy>
    <Window titleid="story_title" modal="true" exitOnClose="true">
        <Label id="subtitle" color="orange" textid="story_subtitle" />
        <Label top="25" color="white" textid="story_content" />
    </Window>
</Alloy> 

By default, every view in the project will have white windows with a vertical layout and gray, left-justified, 12-dp Helvetica labels with a transparent background, as defined by the app.tss file.

However, in the styles defined in the index style file (index.tss) take precedence over the global style file, making the window blue and specifying margin and offset values for all labels in the index view-controller. Additionally, the subtitle ID styles override the styles in the Label element in both index.tss and app.tss.

Finally, any style attribute set in the view XML takes precedence over both the global style and view-specific style files. The orange and white color will be used instead of the gray color specified in global style file, and the larger top offset is used instead of the one set in index.tss.

Platform-Specific Styles

As with views, separate styles may be defined based on the platform and device size in the Titanium style sheets.

To specify platform or device size conditionals:

  1. Place a set of square brackets ([]) directly after the name of the markup element, class name or id name in the TSS file. Do NOT place a space in between the name and brackets. The condition statements will be ignored.

  2. Inside the brackets:

    1. To specify a platform-specific style, use the platform attribute and assign it a platform, such as, android, blackberry, ios, mobileweb, or tizen.

    2. To specify a device-size-specific style, use the formFactor attribute and assign it a device size–either handheld or tablet.

You can use both attributes together.

Alternatively, you can create subfolders, named as the platform, in the styles directory as another way to create platform-specific styles. Refer to Alloy Concepts: Platform-Specific Resources.

The sample style sheet below defines styles for iPhone, iPad, Android and mobile web devices.

// Any device that does not fit any of the below platforms 
"Label": {
    backgroundColor: "#fff",
    text: 'Generic'
},
// iPhone
"Label[platform=ios formFactor=handheld]": {
    backgroundColor: "#f00",
    text: 'iPhone'
},
// iPad and iPad mini
"Label[platform=ios formFactor=tablet]": { 
    backgroundColor: "#0f0",
    text: 'iPad'
},
// Android handheld and tablet devices
"Label[platform=android]": { 
    backgroundColor: "#00f",
    text: 'Android'
},
// Any Mobile Web platform
"Label[platform=mobileweb]": {
    backgroundColor: "#f0f",
    text: 'Mobile Web'
}

Custom Query Styles

Since Alloy 1.4, you can create custom queries to select which styles to apply in both the TSS and XML files. These query statements must return a boolean value. Custom query styles override all styles, that is, class, id, and markup element styles, except the ones defined as attributes in the XML file.

To use a custom query:

  1. Define a conditional statement, which returns a boolean value, and assign it to the Alloy.Globals namespace.

  2. Assign the if attribute to an element in the XML file or in the conditional block of the TSS file to the defined query with the Alloy.Globals namespace.

You may use the if attribute in combination with the platform and formFactor attributes.

For example, suppose you are building an application for the iPhone that displays a scrolling block of text with a title above it and a caption below it, as illustrated by this XML file:

app/views/index.xml
<Alloy>
    <Window>
        <Label id="title" textid="title"/>
        <ScrollView>
            <Label id="content" textid="content"/>
        </ScrollView>
        <Label id="info">TextViewer by BluthCo</Label>
    </Window>
</Alloy>

To take advantage of the various iPhone devices, we need to see if it is running iOS 7 and above, and whether the iPhone is 3.5" or 4". We can define both of these query statements in the initializer file:

app/alloy.js
Alloy.Globals.isIos7Plus = (OS_IOS && parseInt(Ti.Platform.version.split(".")[0]) >= 7);
Alloy.Globals.iPhoneTall = (OS_IOS && Ti.Platform.osname == "iphone" && Ti.Platform.displayCaps.platformHeight == 568); 

In the style file, use these conditional statements to create styles for specific devices. For example, with iOS 7, you can take advantage of the built-in text styles instead of defining all the attribute for a Font object, and since the iPhone 5 is taller, you need to make the ScrollView longer.

app/styles/index.tss
// Default Styles
"#content" : {
    color: 'gray',
    top: '25dp',
    left: '10dp',
    font: {
        fontSize: '12dp'
    }
},
"#info" : {
    color: 'gray',
    bottom: '20dp',
    font: {
        fontSize: '9dp'
    }
},
"#title" : {
    color: 'black',
    top: '15dp',
    font: {
        fontSize: '14dp',
        fontWeight: 'bold'
    }
},
"Window" : {
    layout : 'vertical',
    backgroundColor : 'white'
},
"ScrollView" : {
    height : '415dp'
},
// Query styles
"#info[if=Alloy.Globals.isIos7Plus]" : {
    font : { textStyle : Ti.UI.TEXT_STYLE_FOOTNOTE }
},
"#title[if=Alloy.Globals.isIos7Plus]" : {
    top: '25dp', // compensate for the status bar on iOS 7
    font : { textStyle : Ti.UI.TEXT_STYLE_HEADLINE }
},
"#content[if=Alloy.Globals.isIos7Plus]" : {
    font : { textStyle : Ti.UI.TEXT_STYLE_CAPTION1 }
},
"ScrollView[if=Alloy.Globals.iPhoneTall]" : {
    height : '500dp'
}

Themes

Themes provide a way to change the appearance of an entire GUI, allowing you to customize the styles and assets of the application.

To create a theme, create a folder called themes in your Alloy app directory. In the themes folder, create a folder for your theme. The name of this folder references the name of the theme for configuration and compilation. In your theme folder, create assets and styles folders for your custom images and styles, respectively. The example below creates a theme called 'mytheme'.

  • app

    • assets

      • appicon.png

      • background.png

    • controllers

    • styles

      • index.tss

      • window.tss

    • themes

      • mytheme

        • assets

          • background.png

        • styles

          • app.tss

    • views

      • index.xml

      • window.xml

For assets, all files are overwritten by the copies in the theme's assets folder. In the example, the background.png file in the theme overwrites the file app/assets/background.png, but the app/assets/appicon.png file is used since there is not a similar file in the theme. All asset files are copied to the Titanium project's Resources directory, so all references to assets only need to include the path after the assets folder. The theme's assets folder can have platform- and density-specific folders.

For styles, styles defined in the theme's styles folder merge with and take precedence over the styles defined in app/styles. You can define individual styles per view as well as the global style file app.tss. For example, if a color was specified for a label in the themes/mythemes/app.tss file, this color overwrites the individual style files in app/styles for all labels. However, if a style was defined in one of the individual style files but not in themes/mythemes/app.tss, the styles in app/styles/ are applied. The theme's styles folder can have platform-specific folders.

To use a theme, add it to your config.json configuration file with "theme" as the key and the name of the theme folder as the value. For example:

{
    "global": {
        "theme":"mytheme"
    }, 
    "env:development": {}, 
    "env:test": {}, 
    "env:production": {}, 
    "os:ios": {
        "theme":"green"
    }, 
    "os:android": {
        "theme":"blue"
    }, 
    "dependencies": {}
}

The theme changes based on the platform. Android uses the 'blue' theme, iOS uses the 'green' theme, and Mobile Web uses the 'mytheme' theme.

Style Priorities

When mixing themes, the global style file, view style files and defining styles inline in the XML markup, Alloy applies the styles in the following order from lowest to highest priority:

Style Defined in the...

Example

Global Style File

styles/app.tss

Global Style File in a Theme

themes/<theme_name>/styles/app.tss

Global Style File with Platform-Specific Styles

styles/<platform>/app.tss
OR
styles/app.tss with the [platform=<platform>] syntax

Global Style File in a Theme with Platform-Specific Styles

themes/<theme_name>/styles/<platform>/app.tss
OR
themes/<theme_name>/styles/app.tss with the [platform=<platform>] syntax

View-Controller Style File

styles/<view_controller>.tss

View-Controller Style File in a Theme

themes/<theme_name>/styles/<view_controller>.tss

View-Controller Style File in a Theme with Platform-Specific Styles

themes/<theme_name>/styles/<platform>/<view_controller>.tss
OR
themes/<theme_name>/styles/<view_controller>.tss with the platform attribute

XML Markup

views/<view_controller>.xml

XML Markup with Platform-Specific Styles

views/<platform>/<view_controller>.xmlOR
views/<view_controller>.xml with the platform attribute