Drilldown Navigation with Titanium
Tutorial Details
- Technology: Titanium from Appcelerator
- Difficulty: Intermediate
- Completion Time: 30 Minutes
Drilldown menu systems allow the user to select a menu item, view the item’s page and then either "dig" deeper, or go back up one level. A perfect example is the Settings app on iOS.

Some notes about Android
If you try building this for Android, you will notice that it doesn’t work. That is because Android doesn’t utilize TableViews quite in the same way that iOS does. Here is what Appcelerator employee Dan Thorpe had to say on this thread:
We are going to be looking into creating a core layer that works cross platform on all supported devices. In order to do that, it will basically have to be mostly non-UI and the UI feature will be driven by what’s a capability on all platforms. For instance, blackberry doesn’t provide tabs at all. That being said. If you want a no UI changes App, you’ll be able to create one.
We are also going to be working on exploiting, in a non-cross platform way, platform specific features. For example Android Activities, Intents, Notifications, Services, etc. they will be in the Ti.Android namespace and if you use those features to build a best of breed Android app your users will appreciate it.
For the ideal user experience (UX) you should write to the UI metaphors of the platform the User uses and follow the UX of that platform. That works all ways. An iPhone user would be confused by a true port of an Android app. A blackberry user wouldn’t even be able to use a true port of an iPhone app if they have a keyboard only device.
Titanium’s strength, IMO, is a common set of tooling, a single language, and cross platform library support everywhere we can provide it.
Step 1 Create the project in Titanium
Create a new project in Titanium. The name doesn’t matter. However, if you download my sample code, you can use the "Import Project" button in the toolbar to select the folder containing the tiapp.xml file, which will, as the name implies, import the project.
If we open the Resources/app.js file, we will see the default Titanium code. However, we don’t want most of that code. Whittle it down to this:
// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('#000');
// create tab group
var tabGroup = Titanium.UI.createTabGroup();
// create base UI tab and root window
var win1 = Titanium.UI.createWindow({
title:'Tab 1',
backgroundColor:'#fff'
});
var tab1 = Titanium.UI.createTab({
title:'Tab 1',
window:win1
});
// our drilldown menu goes here
// add tabs
tabGroup.addTab(tab1);
// open tab group
tabGroup.open();
Now we have a good starting point. You are probably wondering about the tab group with 1 tab. For some reason with Titanium you need to use tabs to create a drilldown menu. Let’s go ahead and hit “Launch” in Titanium and see what we get.

Uh oh, that’s no good. We don’t want to have a big tab down there!
Step 2 Removing the visible tab bar
Fortunately this is a rather easy fix. Simply set the property ‘tabBarHidden’ to true for win1. While we are at it, let’s rename the window. Your code should now look like this:
// create base UI tab and root window
var win1 = Titanium.UI.createWindow({
title:'My Drilldown',
backgroundColor:'#fff',
tabBarHidden: true
});
Ah, that’s better.

Step 3 Adding the first TableView
The most important part of this app is the TableView, which will display the rows of options to the user. Let’s create it now and put it in where the comment that says "our drilldown menu goes here":
// create the main menu container
var main_menu = Ti.UI.createTableView({
style:Titanium.UI.iPhone.TableViewStyle.GROUPED,
scrollable:false
});
win1.add(main_menu);
Notice how we have prevented the table from being scrolled. This is sometimes desirable if you only have a few menu items.
Now that we have created the main table, let’s add the rows that will "link" to the sub-TableViews:
// first option row
var firstItemRow = Ti.UI.createTableViewRow({
hasChild: true
});
var firstItemLabel = Ti.UI.createLabel({
left: 9,
text: "This is the first option"
});
firstItemRow.add(firstItemLabel);
main_menu.appendRow(firstItemRow);
// end first option row
Okay, so we did a few things in that block. First, we created a blank table row and set the ‘hasChild’ property to true. This make the little gray arrow show up on the right side of the row. Next, we created a label and added it to the once-blank table row. We then appended the row to the menu. Let’s repeat this process 3 more times so that we now have 4 main menu options, and code that looks like this:
// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('#000');
// create tab group
var tabGroup = Titanium.UI.createTabGroup();
// create base UI tab and root window
var win1 = Titanium.UI.createWindow({
title:'Tab 1',
backgroundColor:'#fff',
tabBarHidden:true
});
var tab1 = Titanium.UI.createTab({
title:'Tab 1',
window:win1
});
// create the main menu container
var main_menu = Ti.UI.createTableView({
style:Titanium.UI.iPhone.TableViewStyle.GROUPED,
scrollable:false
});
// first option row
var firstItemRow = Ti.UI.createTableViewRow({
hasChild: true
});
var firstItemLabel = Ti.UI.createLabel({
left: 9,
text: "This is the first option"
});
firstItemRow.add(firstItemLabel);
main_menu.appendRow(firstItemRow);
// end first option row
// second option row
var secondItemRow = Ti.UI.createTableViewRow({
hasChild: true
});
var secondItemLabel = Ti.UI.createLabel({
left: 9,
text: "This is the second option"
});
secondItemRow.add(secondItemLabel);
main_menu.appendRow(secondItemRow);
// end second option row
// third option row
var thirdItemRow = Ti.UI.createTableViewRow({
hasChild: true
});
var thirdItemLabel = Ti.UI.createLabel({
left: 9,
text: "This is the third option"
});
thirdItemRow.add(thirdItemLabel);
main_menu.appendRow(thirdItemRow);
// end third option row
// fourth option row
var fourthItemRow = Ti.UI.createTableViewRow({
hasChild: true
});
var fourthItemLabel = Ti.UI.createLabel({
left: 9,
text: "This is the fourth option"
});
fourthItemRow.add(fourthItemLabel);
main_menu.appendRow(fourthItemRow);
// end fourth option row
win1.add(main_menu);
// add tabs
tabGroup.addTab(tab1);
// open tab group
tabGroup.open();
Your app should now look like this:

Step 4 Creating the sub-menus
Creating the sub-menus is a simple process. You create a new window and add things to it. However, the trick is in displaying this new window as part of a drilldown. I assume by now you are familiar with making windows in Titanium, so I am just providing some filler code below that integrates well with the code above:
// sub window 1
var sub_win1 = Ti.UI.createWindow({title:'Sub-Window 1'});
var sub_table1 = Ti.UI.createTableView({style:Titanium.UI.iPhone.TableViewStyle.GROUPED});
var sub_row1 = Ti.UI.createTableViewRow();
var sub_label1 = Ti.UI.createLabel({left:9, text: "This is a sub option!"});
sub_row1.add(sub_label1);
sub_table1.appendRow(sub_row1);
sub_win1.add(sub_table1);
// sub window 2
var sub_win2 = Ti.UI.createWindow({title:'Sub-Window 2'});
var sub_table2 = Ti.UI.createTableView({style:Titanium.UI.iPhone.TableViewStyle.GROUPED});
var sub_row2 = Ti.UI.createTableViewRow();
var sub_label2 = Ti.UI.createLabel({left:9, text: "This is a sub option!"});
sub_row2.add(sub_label2);
sub_table2.appendRow(sub_row2);
sub_win2.add(sub_table2);
// sub window 3
var sub_win3 = Ti.UI.createWindow({title:'Sub-Window 3'});
var sub_table3 = Ti.UI.createTableView({style:Titanium.UI.iPhone.TableViewStyle.GROUPED});
var sub_row3 = Ti.UI.createTableViewRow();
var sub_label3 = Ti.UI.createLabel({left:9, text: "This is a sub option!"});
sub_row3.add(sub_label3);
sub_table3.appendRow(sub_row3);
sub_win3.add(sub_table3);
// sub window 4
var sub_win4 = Ti.UI.createWindow({title:'Sub-Window 4'});
var sub_table4 = Ti.UI.createTableView({style:Titanium.UI.iPhone.TableViewStyle.GROUPED});
var sub_row4 = Ti.UI.createTableViewRow();
var sub_label4 = Ti.UI.createLabel({left:9, text: "This is a sub option!"});
sub_row4.add(sub_label4);
sub_table4.appendRow(sub_row4);
sub_win4.add(sub_table4);
Step 5 Making the main menu items do something
Here is where the magic happens: events. By binding a function to the ‘click’ event listener we can handle what happens when a row is selected in a TableView. Let’s go!
// add the event to the first item
firstItemRow.addEventListener('click', function (e) {
tab1.open(sub_win1);
});
// add the event to the second item
secondItemRow.addEventListener('click', function (e) {
tab1.open(sub_win2);
});
// add the event to the third item
thirdItemRow.addEventListener('click', function (e) {
tab1.open(sub_win3);
});
// add the event to the fourth item
fourthItemRow.addEventListener('click', function (e) {
tab1.open(sub_win4);
});
Surprisingly simple, isn’t it! We just go back to the “invisible” tab we have and open a new window. If you hit “Launch” for this application in Titanium, you can see that the back buttons are automagically generated for you!

Conclusion and Extension
“2-level navigation is great,” you might say, “but I want 3 or 4 or 5 level navigation!” Fortunately, you can simply follow the same procedure as was just shown above! Remember, no matter how far deep you are in the navigation, you can always call tab1.open() and move even deeper. Titanium certainly is a fantastic, flexible tool.

this is some kind cool… for real thats a good tip… but like tutorial… im not shure.. i think you need to change the Difficulty: to novice… but is ok … i really like it.. thanks :D ….
Well, it assumes knowledge of some basic Titanium information, so I figured it wasn’t novice. But you are right, it is more towards novice than expert.
Hi, nice tutorial :)
But I have a question:
Why you did not use a navigationGroup ? Creating a tabGroup that it’s not used doesn’t look ok to me especially when you have a dedicated control for this.
@Dan
I can’t remember what problem I had with navigationGroup, but I remember that I struggled (several months ago) getting a navigationGroup to work. I had found some references that a hidden tab group was the way to go, and it worked. Maybe it has been fixed, but I know this method works. In any case, the process is more or less the same it looks like from reading the API docs.
You can use this even if you have multiple tabs, I have a complex data app that uses a similar approach to multiple drill downs in different tabs. To do this and hide the tab bar easily create the sub windows as modal windows.
Also you don’t need to create labels for the rows you can simply populate using an array specifying the title element with the text you want in the row. This way you can really clean up up and reduce the amount of code. For example you create an array of arrays specifying the elements title and hasChild and pass array name as the data parameter to the createTableView function.
Yes, you can add multiple tabs and do the process on each tab.
Cool, I wasn’t aware of that. If I understand correctly though, if you need to customize the rows (ie, there might be different inputs and switches on each line) then this method works better.
tabBarHidden: true -> thanks for this useful tip. Many days ago, I wonder how can hide tabbar, and now I find the right solution.
Hi,
in order to get the same behaviour on Android, you should create a tiny adaptation layer that takes care of window creation, like the functions you can find in this pastie: http://pastie.org/1136090.
The idea is to get completely rid of the tab group on Android, creating a simple standalone window as the main window (I confirm the Ti.UI.iPhone.NavigationGroup to not work as expected), whilst enabling a consistent behaviour across the two platforms.
The first function is to be used for creating the main app window (usually in app.js), while the second is to be used every time you need to open a new window.
I hope this will hep.
Excellent work Olivier, that takes care of Android nicely!
Thanks Alec,
lately I’ve been struggling a lot with how Titanium handles the slight discrepancies in the UI of the two platforms, especially with respect to the management of the layout of views and subviews.
Cheers!
Olivier
is there a complete sample of making this work on Android?
I have implemented the Navigation Groups for my iPhone application using the Titanium UI but I need to use this work around to get it functioning on an Android device
Where can i download sample code ?
Love it – thanks heaps.. Great tutorial
Only thing is tried to use leftimage: ‘test.png’ in the code to get an image to the left of the text but cannot nut it out..
Apart from that, gives me HUGE hope of creating a decent app using programming..
if anyone knows how to add this to the code (as I’m going nuts), please let me know :-)
Are you sure you put the test.png in the Resources folder? Also it is leftImage (with a capital i), not leftimage.
I started with this tutorial which was very good. I needed the data dynamic (loaded via XML) though and 3 levels deep, not just two. I had issues at first but eventually figured it out on my own. If you guys need to do something similar, check my thread over at the appcelerator forums. The answer should be right after the question.
http://developer.appcelerator.com/question/70051/looping-through-xml
Nice job! Glad to see you got everything figured out.
I am sure other people will have the same issue as you.
Ronnie;
thanks for sharing your code. is it possible to have the third level be a detail page filled with xml? For instance when you click the course Tactical B1, you get the details of that course
Hi thanks for the tutorial, I’m very new to Titanium and was following this tut. However, if I traverse over the menu items a few time, the “next” sub menu dissappears, Is that normal?
// Drillin Down
Tab1
Suboption 1
//Drill Up
Suboption 1
Tab 1
And finally if I drill down again:
//Drill Down
Tab 1
Suboption 1 ( MISSING!)
Hope someone can help… thanks!
Nice tutorial, but I’ve a question:
if I open a sub-window, I see the menu in the sub-window. If I go back to the main window and re-open the same sub-window, the menu in that sub-window disappeared…
How can I fix it?
Don’t know if you have fixed this yet, but I have found a solution. I wrapped the entire thing in a function and then call it at the end of the code like this.
// add the event to the first item
firstItemRow.addEventListener(‘click’, function (e) {
loadTableView();
tab.open(sub_win1);
});
// add the event to the second item
secondItemRow.addEventListener(‘click’, function (e) {
loadTableView();
tab.open(sub_win2);
});
// add the event to the third item
thirdItemRow.addEventListener(‘click’, function (e) {
loadTableView();
tab.open(sub_win3);
});
// add the event to the fourth item
fourthItemRow.addEventListener(‘click’, function (e) {
loadTableView();
tab.open(sub_win4);
});
}
loadTableView();
/////////////////////////////////////////////////////
tabGroup.addTab(tab1);
tabGroup.open();
Then I call the same function before opening the sub_win.
Hope that helps
I am having the same issue, it will working on Android though…
hi,
I’m getting an error when I click on the option buttons… to display the sub-menus’
and the app is crashing
i’m using android emulator..
any thoughts?
thanks