API Development

Create a Custom Android Actionbar in Titanium with Icons and Optional Badges

Ray Belisle is an Appcelerator Titan, Appcelerator Trainer and Developer from Calgary, Canada with 6+ years using Appcelerator. He has been developing and sharing his knowledge with the community throughout his career. Feel free to follow him on Twitter or connect with him at mobilexperience.ca

Badges? We don’t need no stinking badges!

Adding custom icons and badges to your top bar in iOS is fairly straightforward. You can create right and left nav views, embed multiple objects in those views, position them to create any view you want, including a icon/badge combination.

The Android Actionbar is a much different in Titanium. Icons in Actionbar menu items are supported, badges are not and so creating a similar UI that matches your iOS app can be a challenge.

Recently, I encountered this exact issue. I wanted a consistent UI in both iOS and Android. A custom toolbar, custom icons, custom colors and badges all that can be updated at runtime adding or removing menu icons and updating badges on the fly.

The approach I took is to use the built-in Ti Android Actionbar and use Menu Items to hold the icons/badges. Menu Items in Android have a special property, the ActionView. This view can hold items that will display on Android as a menu item. This is exactly what we need, so on to creating the icons and badges.

To mimic the iOS interface, I used an ImageView embedded in the ActionView to display the badge image I created. I decided to use the fontAwesome fonts to create the menu items and badges for both iOS and Android. This provides consistency in the app menu and works for both platforms. See the Titanium docs on using fonts in your apps if you have never done that before.

Here is an example of the menu structure in the xml file for an Actionbar with a custom ‘Alert’ icon:

<alloy>
  <window id='win' backgroundColor="white" onOpen="updateActionView">
    <actionbar id="actionbar" title="Toolbar Demo"></actionbar>
    <menu>
      <menuitem showAsAction="Ti.Android.SHOW_AS_ACTION_ALWAYS" title="Alerts" >
        <actionview>
          <imageview id="alerts" onClick="alertClicked"></imageview>
        </actionview>
      </menuitem>
    </menu>
  </window>
</alloy>

A few things to note here:

  • The onOpen="updateActionView" attached to the window allows me to call a function to generate the icons and badges for the Actionbar. You need to call something to generate the images you need for the Actionbar.
  • When using an ActionView, you must set showAsAction to either Ti.Android.SHOW_AS_ACTION_ALWAYS or Ti.Android.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW. See the Titanium docs for more info.
  • You must attach the onClick event to the image itself. The ActionView does not respond to regular menu item events.

Now that we have the structure for the ActionBar, let’s look at the associated code:

function updateActionView() {

//Call the generateIcon function, passing the icon you want to use and the badge icon and layout.

var alertIcon = generateIcon({
icon : 
  {
    text : '\uf0f3’, // bell icon
    font : {
      fontSize : 30,
      fontFamily: 'FontAwesome'
      },
    color : "#fba61a"
  },
badge : 
  {
    text : '\uf111’, //circle icon
    color : "red",
    font : {
      fontSize : 16,
      fontFamily: 'FontAwesome'
    },
    top:2,
    right : 2
  },
  width : 40
});

//When the alertIcon view is returned, assign it to the $.alerts imageView object in the xml file by converting to an image Object

alertIcon.toImage(function(img) {
  $.alerts.image = img;
});
}
function generateIcon(iconInfo) {

//Here we are just going to create the icon and badge as specified and return a view with the information rendered.

//First generate a view that will be assigned to the icon

var iconWrapperView = Ti.UI.createView({
  height : Ti.UI.SIZE,
  width : Ti.UI.SIZE
});

//Create a label object with the icon information
var icon = Ti.UI.createLabel(iconInfo.icon);

//If badge information is assigned, then create the badge label

if (iconInfo.badge) {
  var badge = Ti.UI.createLabel(iconInfo.badge);
}

//Put the icon and the badge into the iconWrapperView

iconWrapperView.add(icon);
if (iconInfo.badge) {
  iconWrapperView.add(badge);
}

//Now we need to wrap the view into another with spacing. When you start adding additional icons to the Actionbar, need some spacing. This wrapperView will add the specified spacing

var wrapperView = Ti.UI.createView({
  width : iconInfo.width
});

//Now add the iconWrapperView to the spaced view. It will be centered by default.

wrapperView.add(iconWrapperView);

return wrapperView;

}

function alertClicked() {
  alert ("alert Clicked!");
}

That’s it!

By default, this code generates an Alert/Bell icon with a red “badge” indicating you have alerts to respond to.
Since you can use any font, view, image as part of creating your ‘Icon View’ for the ActionBar, you can be creative and put whatever you want in your icon.

For example, this alert badge consists of the same red circle with an additional label showing an Alert Count.
If you need to update your icons at runtime, you simply generate a new icon/badge combo and assign it to the appropriate imageView!

Happy Coding!