Tabris.js 1.1: Custom themes on Android

July 3, 2015 | 5 min Read

UPDATE 1: With Tabris.js 1.1 released to production, we have removed the “sneak peak” indication from this article.

UPDATE 2: Starting with Tabris.js 2.0.0-beta1 the base theme to inherit from has been renamed to DarkAppBar and the theme preference now expects an Android resource reference to a theme. See the tabris documentation for details.


In a previous blogpost we discussed how to choose between one of the predefined themes for your Tabris.js app on Android. Basically it boiled down to setting the correct preferences value in your cordova config.xml. In this second part of the miniseries we will have a look at how to provide your own custom Android theme. :)

Creating and applying a custom Android theme only takes three simple steps:

  1. Create an Android theme declaration
  2. Enable the Tabris.js cordova build to include your custom theme
  3. Let the Tabris.js Android app apply the custom theme

The snippets you will find throughout this blog post can also be found in this gist. In addition you can create a custom theme for your app right now by using the tabrisjs.com build service. Let’s get started!

Theme declaration

Starting with Tabris.js 1.1 the Android client makes use of the Android appcompat support library, giving you a consistent material design look and feel across all supported Android versions (currently Android 4.0+). During the migration process we were able to create a very lean base theme from which you can inherit to create your own theme.

One of the corner stones of material design is the use of color to give an app a strong feel of branding. The following example shows you an Android theme providing base colors for your app:



    
        <item name="colorPrimary">#3F51B5</item>
        <item name="colorPrimaryDark">#303F9F</item>
        <item name="colorAccent">#FF4081</item>
    

Using the above theme in your app provides a very individual look that clearly indicates your brand. Note how the accent color is applied throughout the UI elements as a tinting color.

A few things should be mentioned about the theme declaration. First of all we reference @style/Theme.Tabris.Light.DarkActionBar as our parent theme. You should always inherit from one of our three base themes as to not break styling. Make sure to use the dot notation (instead of underscores) when using a theme as the parent of a new theme.

Another aspect of the custom theme is the missing namespace of the color* attributes. They do not use the android: namespace since these attributes come from the appcompat theme, from which we inherit internally. When overriding standard Android attributes you would use the android: namespace as usual. For more information on how to create themes based on appcompat see this blogpost or this blogpost.

Now that we have created our custom theme it is time to apply it in our own Tabris.js app. The integration is pretty simple and makes use of our cordova based build system on tabrisjs.com. You can find the entire project as gist on github.

Copy theme into Android platform

The first step is to put the theme declaration shown above into your Tabris.js project. Since we are dealing with a Tabris.js cordova build, you will have a cordova folder in the root folder of your app. Our theme will live in that cordova folder as well. Our theme goes into cordova/resources/android/res/values/sandbox_themes.xml. Note the sandbox_ (app specific) prefix in front of the file name. Using a prefix for all of your resources is good practice as it prevents potential conflicts with Tabris.js or other third party libraries.

The next step is to copy our custom resources into the Android Cordova platform before the build step happens. To automate this process we create a custom build hook that performs this task:

var fs = require('fs');
var path = require('path');

module.exports = function(context) {
  if (fs.existsSync(path.join(context.opts.projectRoot, "platforms/android")) {
    var srcDir = path.join(context.opts.projectRoot, "resources/android/res");
    var targetDir = path.join(context.opts.projectRoot, "platforms/android/res");
    copyRecursiveSync(srcDir, targetDir);
  }
}

The above snippet checks whether we have a platform called android installed and copies all the content from resources/android/res (including our themes.xml) into the android platform under platforms/android/res. The copyRecursiveSync() function is deliberately left out in the snippet but can be found on github. We place this build hook into the cordova folder under cordova/scripts/android/afterPlatformAdd.js.

Apply the theme

The final step is to configure our app to apply the build hook and to make use of our theme. To do so we modify the cordova/config.xml as shown below:



  ..

  

  
    
  

The integration of the build hook is standard Cordova but the Theme preference has to follow a certain scheme. It references a fully qualified class field name. The value of the Theme preference starts with the app ID as given in the widget tag. In our case it’s com.eclipsesource.sandbox.theme. The next segment is R.id followed by the theme name as defined in the themes.xml we looked at above. The name of theme in the theme file is Theme.Sandbox but since we are referencing it as a fully qualified name the dot is changed to an underscore, resulting in Theme_Sandbox. The fully qualified name is therefore com.eclipsesource.sandbox.theme.R.style.Theme_Sandbox.

Running the build

The theming support requires Tabris.js 1.1 and can be run on our build service on tabrisjs.com.

In case you want to build an app with a custom theme on your local machine you would need to have a Tabris.js Pro account and download the Android platform from the download page. Then you could simply copy the entire content of the Cordova folder into the root directory of your app and add the Android platform via the cordova-cli. For more info on how to build your app locally see the tabris documentation.

Wrap Up

Summing it all up, it only took three steps to provide a custom Android theme for our Tabris.js app. First we created our custom theme, inheriting from a Tabris.js theme, then we created a build hook that copies our theme into the Android platform and finally we wired the build hook and applied the theme in the config.xml.

The theme above merely provides the base colors of your app but you can easily overwrite any attributes like button, text view or edit text appearance. Simply place the graphics assets into the appropriate drawable folder and reference them in your themes.xml. For more information on general Android theming see the official docs.