Action Bar Module for Titanium Mobile

I recently re-wrote my Titanium mobile template (StoreApp) to support Android devices. In the process I coded the a basic foundation for an action bar module. The Titanium SDK doesn’t support action bars yet but there is a task logged in Appcelerator’s JIRA instance for this so it should be coming soon. For now you can use this.

It’s been awhile since I posted something on this blog so I’m hoping this free module makes up for lost time… let’s dive in!

Figure 1. Action bar from Honeycomb Gallery app.

The main reason for creating this module was to provide a navigation bar in my template application. The native android action bar does more then what I need. You can add an app logo/icon, different navigation bar types, acton buttons and a drop down ‘more’ button (see Figure 1). For now we’ll just stick to basic navigation tabs. You can easily extend this if you want for your project. I might add more features based for future apps.

I want the module UI to look familiar to Android users so I read the design and api guides from Google. I mainly focused on the Navigation tabs. I also decided to support iOS devices since there really was no reason to only use this on Android. Some apps in the Apple AppStore already use this design pattern (Google Chrome for example). I still use a TabGroup on the iOS version of the StoreApp template but that may change in future releases.

Figure 2. Here are some basic navigation tabs.

In Figure 2 you can see the basic layout design for the navigation tabs based on Google design guide. The tabs will¬†stretch¬†out to fill up the horizontal space of the parent container (window or view). The height will be the recommended 48dp but you can change this. I’ll use the second color theme as the default setting. You can override these settings in the action bar constructor call. Also the navigation tabs are wrapped in a navigation group view so we can add more to the action bar down the road (like app icon and action buttons). Now with our basic design done we can get to some code.

I’m going to use the recommended CommonJS module pattern to build and include our action bar. To start it off I created a simple module with the ActionBarView constructor.

function ActionBarView(args) {
   var ActionBar = Ti.UI.createView({
      height : '48dp,
      backgroundColor : '#b5b5b5',
      layout : 'horizontal',
      top : 0
   });

   return ActionBar;
}

module.exports = ActionBarView;

 


The background color will serve as the top and bottom border for the action bar. I didn’t use the normal view border because I don’t need a border on the left and right. The layout is set to horizontal to keep each tab relative to the previous one.

Next I need a factory function to build the navigation group to hold the tabs. This is just another view with a horizontal layout to manage the tab components. Creating the navigation group gives us flexibility later when we want to add more to the action bar. Here’s the basic function.

function createNavigationTabGroup(tabs){
   var _tabs = tabs || [],
      _tabCount = _tabs.length,
      _i = 0,
      _deviceWidth = Ti.Platform.displayCaps.platformWidth,
      _width = (_deviceWidth / _tabCount) - 1, //pixel for separator
      _selectedTab,
      _view = Ti.UI.createView({
         layout : 'horizontal',
         width : Ti.UI.FILL,
         top : 1,
         bottom : 1
      });

   for(; _i < _tabCount; _i++){
      _tabs[_i].width = _width;
      _tabs[_i] = buildTab(_tabs[_i]);
      _view.add(_tabs[_i].tabView);
      _view.add(tabSeperator());
   }
}

 


I use the underscore prefix to keep track of local function variables. The createNavigationTabGroup function expects a tabs array object with settings for each tab. It will loop through the array and build each tab then add to the navigation view. You’ll notice I position the navigation view 1px from the top and bottom so the action bar view background can show as a top and bottom border. There are two new factory functions I use in the loop to build each tab and tab separator. Let’s take a look at them.

function tabSeperator(){
   var seperatorView = Ti.UI.createView({
         backgroundColor : '#cdcdcd',
         width : 1
      }),
      seperator = Ti.UI.createView({
         height : '32dp',
         backgroundColor : '#b5b5b5'
      });

   seperatorView.add(seperator);
   return seperatorView;
}

 


The tabSeparator function is pretty straight forward. It creates a view with a nested view to build a 1px bar centered vertically.

function buildTab(params){
   var _params = params || {},
      _tabView,
      _tabLabel,
      _config = {
         id : _params.id,
         text : _params.text || "Nav",
         selectedColor : _params.selectedColor || '#00b7e3',
         backgroundColor : _params.backgroundColor || '#cdcdcd',
         textColor : _params.textColor || '#5f5f5f',
         width : _params.width || 'auto',
         selected : _params.selected || false
      };

   if(_config.selected){
      _selectedTab = _config.id;
   }

   _tabView = Ti.UI.createView({
      id : _config.id,
      backgroundColor : _config.selectedColor,
      width : _config.width,
      layout : 'vertical'
   });

   _tabLabel = Ti.UI.createLabel({
      text : _config.text,
      color  : _config.textColor,
      backgroundColor : _config.backgroundColor,
      textAlign : Ti.UI.TEXT_ALIGNMENT_CENTER,
      height : _config.selected ? '42dp' : '46dp',
      left : 0,
      right : 0,
      font   : {
         fontSize   : '12dp',
         fontWeight : 'bold'
      }
   });

   _tabView.add(_tabLabel);

   _tabView.addEventListener('click', function() {
      navigationGroup.fireEvent(
         'ActionBar.NavigationTab:Click',
         { tabId : _tabView.id }
      );
   });

   return {
      tabView : _tabView,
      select : function(bool){
         _tabLabel.height = bool ? '42dp' : '46dp'
      }
   };
}

 


The buildTab function creates the UI components required for a tab view. A basic view provides the container as well as the selected indicator. Next add a label in the view to cover the background color and display the tab text. When a tab is selected then reduce the height of the label to show the background… about 4dp. The click event handler will fire the navigation group tab click event with the tab id. This will get used to set the selected tab and so your app can figure out what to do next (ex. switch views or display sub-menu). The object returned contains the tab view and a select function to handle the tab UI state.

That’s it! The main chunks of this module are done. Now I just need to cleaned up the code a bit. Add all the required functions into the module file and cleaned up the variables with a theme object. Enjoy and let me know what you think. I’ll keep hacking away at this to make it better and add some of the other action bar features. You can download the latest code from Github. I added the combined code below…. hack away!

 

This entry was posted in Code, Training and tagged , , , , , , , , , , . Bookmark the permalink.

6 Responses to Action Bar Module for Titanium Mobile

  1. Arie says:

    hello, how to show different view on each action bar?

    • TiHelper says:

      You can use a ScrollableView to help manage what is displayed based on tab selection. When the ActionBar.NavigationTab:Click event is fired you can switch the view with ScrollableView.scrollToView().

      You can see an example of this on the Appcelerator-Titan github project called “App”. That project also has a basic action bar module that is a bit different from what I created.

  2. Josh Roesslein says:

    Nice article! We recently wrapped up development for the Action Bar Tabs in Titanium.
    The API is exactly the same that you already use for TabGroups. Basically once you bump your target API version in your manifest above 11 you get the action bar style tabs. On older devices we fall back to the older TabHost/TabWidget style.

    Should be available in our next major release. Feel free to try it out in a master branch CI build! Let me know if you have any feedback.

    Josh Roesslein
    Titanium Mobile Engineer

    • Igor Santos says:

      Sorry for the stupid question, but I’m still quite noob with Titanium.
      I want to create an app with the ActionBar, and you said it’s already available under the master branch and it’s also the same as TabGroups. What does this mean?
      1. I can code my app with a normal TabGroup and, and I update Titanium SDK, I’ll get the fancy ActionBar (given that I’m targetting API 11+)?
      2. How can I update my Titanium Studio to use a custom downloaded version of the SDK (like the one on GitHub)?

  3. Felix says:

    Hi, the click event doesn’t work. Thanks for your code.

  4. No need to emulate unless your user is running a pre-4.0 device. Titanium provides the Holo-themed ActionBar and Stacked Tabs. Check this Gist for reference: https://gist.github.com/ricardoalcocer/5339699

Leave a Reply to Arie Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>