TabStrip for Titanium Mobile
Posted on: February 28, 2011
- In: IPhone Development | Mobile | titanium | UI
- 7 Comments
Another UI component we found missing in Titanium Mobile was a TabStrip, like the one you would find in Facebook’s Three20 project for the iPhone where you can have as many tabs as you like and have them fit nicely on the top of the screen because they are scrollable.
After spending some time we came up with a solution that we believe works really well. It takes in any number of labels and will dynamically size the horizontal scroll width and provide arrow indicators that more tabs exist in either direction. Just pass in an onselect function and you can get the tab index for a selected tab – with this you can change the data on the screen. The code below uses the days of the week as an example and will swap out the table view’s data based on the tab selected.

function createTabStrip(options) {
options = options || {};
params = {
labels: options.labels || [],
onselect: options.onselect || null,
top: options.top || .1,
height: options.height || 40,
backgroundColor: options.backgroundColor || '#000',
gradientColor: options.gradientColor || '#444',
selectedColor: options.selectedColor || '#fff',
unselectedColor: options.unselectedColor || '#999',
fontSize: options.fontSize || 14
}
var labelViews = [];
var lastSelectedLabel = null;
var totalWidth = 0;
var containerView = Titanium.UI.createView({
top:params.top,
height:params.height,
width:320,
backgroundColor:params.backgroundColor,
backgroundGradient: {
type:'linear',
colors:[
{color:params.gradientColor,position:0.0},
{color:params.backgroundColor,position:0.50},
{color:params.gradientColor,position:1.0}
]
}
});
var leftArrow = Ti.UI.createLabel({
text:String.fromCharCode(171),
font:{fontSize:params.height / 2,fontWeight:'bold'},
color:params.selectedColor,
height:params.height,
width:15,
top:params.top,
left:2,
textAlign:'left',
visible:false
});
containerView.add(leftArrow);
var scrollView = Titanium.UI.createScrollView({
layout:'horizontal',
top:params.top,
left:17,
height:params.height,
width:286
});
containerView.add(scrollView);
var rightArrow = Ti.UI.createLabel({
text:String.fromCharCode(187),
font:{fontSize:params.height / 2,fontWeight:'bold'},
color:params.selectedColor,
height:params.height,
width:15,
top:params.top,
right:2,
textAlign:'right',
visible:false
});
containerView.add(rightArrow);
scrollView.addEventListener('scroll', function(e) {
leftArrow.visible = e.x > 5;
rightArrow.visible = e.x < scrollView.contentWidth - scrollView.width;
});
containerView.labels = function(labels) {
params.labels = labels;
resetLabels();
}
containerView.selectTab = function(index) {
select(labelViews[index]);
}
function resetLabels() {
totalWidth = 0;
labelViews = [];
var oldLabels = scrollView.children;
if (oldLabels) {
for (var i = 0,count = oldLabels.length; i < count; i++) {
scrollView.remove(oldLabels[i]);
}
}
var labels = params.labels;
for (var i = 0,count = labels.length; i < count; i++) {
var button = createButton(labels[i], i);
scrollView.add(button);
}
scrollView.contentWidth = totalWidth;
rightArrow.visible = totalWidth > scrollView.width;
}
function createButton(title, index) {
var buttonView = Ti.UI.createView({
top:params.top,
height:params.height
});
var label = Ti.UI.createLabel({
text:title,
font:{fontSize:params.fontSize,fontStyle:'bold'},
width:'auto',
textAlign:'center',
height:params.height,
touchEnabled:false
});
label.index = index;
labelViews.push(label);
buttonView.add(label);
showAsUnSlected(label);
buttonView.addEventListener('click', function(e) {
select(e.source.children[0]);
});
buttonView.width = label.size.width + 20;
totalWidth += buttonView.width;
if (index == 0) {
showAsSelected(label);
}
return buttonView;
}
function select(label) {
if (lastSelectedLabel) {
showAsUnSlected(lastSelectedLabel);
}
showAsSelected(label)
if (params.onselect) {
params.onselect(label.index);
}
}
function showAsSelected(label) {
label.color = params.selectedColor;
label.getParent().borderWidth = 1;
lastSelectedLabel = label;
}
function showAsUnSlected(label) {
label.color = params.unselectedColor;
label.getParent().borderWidth = 0;
}
resetLabels();
return containerView;
}
var tableData = [
[{title:'Monday Data'}],
[{title:'Tuesday Data'}],
[{title:'Wednesday Data'}],
[{title:'Thursday Data'}],
[{title:'Friday Data'}],
[{title:'Saturday Data'}],
[{title:'Sunday Data'}]
];
var window = Titanium.UI.createWindow({
fullscreen:false,
backgroundColor:'#fff',
title:'TabStrip'
});
var tabStripView = createTabStrip({
labels:['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],
onselect: function(index) {
//This is so you don't get flickering
tableView.hide();
tableView.setData(tableData[index]);
setTimeout(function() {
tableView.show();
}, 300);
}
});
window.add(tabStripView);
var tableView = Ti.UI.createTableView({
top:tabStripView.height
});
window.add(tableView);
var navGroup = Ti.UI.iPhone.createNavigationGroup({
window:window
});
var main = Ti.UI.createWindow();
main.add(navGroup);
main.open();
tabStripView.selectTab(0);
7 Responses to "TabStrip for Titanium Mobile"
Hi.
Does it works on Android??
Hey man, just wanted to say your a life-saver. I’ve been playing for hours with the Kitchen Sink’s scrolling toolbar, and nothing clicked with my app until I implemented your code. Again, thanks a billion.
Hi Brian,
Thanks a ton for the code. I am trying a similar thing on that also works on Android.
Thanks a ton for the code briann,, life safer
February 28, 2011 at 9:44 am
Hi,
Thanks for the great instructions. Hope you can help me on this: On some of my pages I would like to have the tabstrip (included on the specific pages I choose) I don’t want a table view but just the bar (like a menubar) Should/can I use Ti.include(“tabstrip.js”); ??
After that I would like to accomplish that when someone clicks on Monday that this links to monday.js and click on wednesday it links to wednesday.js
Hope you can help me and I am shure that a lot of people would like to know how to code this.
Thanks in advance,
Danny
February 28, 2011 at 7:35 pm
Yes I would probably just wrap the createTapStrip function in a js file so you can call it from anywhere and add to any window or view.
Also it’s up to you how you handle the onselect – this code used a table view as an example. So you could always do something like:
onselect: function(index) {
var w = Ti.UI.createWindow({
url:’monday.js’,
top:80
});
w.open();
}
Of course you would want to dynamically determine the actual js file to use by the index, so maybe just store those values in an array.
February 28, 2011 at 8:00 pm
Hi Brian,
Thanks for taking time on answering my question. If you have some spare time I would love to see some example.
If you don’t have time that’s no problem at all.
Best regards Danny