Category Archives: Learn Titanium Appcelerator

Develop iPhone, iPad and Android apps using Titanium Appcelerator. Interesting resources, news and opinions.

Making a combo-box in Titanium Appcelerator – code and video

Sometimes we need a true combobox for our projects but iPhone SDK does not have a native one (at least from what I know) and of course neither has Titanium.

So we will build one. A “true” iPhone or Ipad combobox that allows you to use the same textfield to input arbitrary text or select a value from a UIPicker element.

Updated with @CJ_Reed’s screenshot and code at the final of the tutorial.

Let’s see the video first, then we’ll get to work:

Ok, what do we need for this iPhone combobox ?

First of all we need a textField to accept input from the user. Titanium lets you set the leftButton and rightButton for this textField while constructing it. So we will take advantage of this and create a textField as it follows:

var my_combo = Titanium.UI.createTextField({
	hintText:"write your name or select one",
	height:40,
	width:300,
	top:20,
	borderStyle:Titanium.UI.INPUT_BORDERSTYLE_ROUNDED
});

Nothing special, a regular textField with a hint for the user that will disappear when the textField has a value.

Now we need to create the rightButton for it.

We will use a system button provided by Apple (Titanium.UI.iPhone.SystemButton.DISCLOSURE) only that we will rotate it 90 degrees to serve our purpose. This is the code that creates the rightButton and the transformation applied to it.

var tr = Titanium.UI.create2DMatrix();
tr = tr.rotate(90);
 
var drop_button =  Titanium.UI.createButton({
		style:Titanium.UI.iPhone.SystemButton.DISCLOSURE,
		transform:tr
});

Now that we have the rightButton as we need it, the textField constructor becomes:

var my_combo = Titanium.UI.createTextField({
	hintText:"write your name or select one",
	height:40,
	width:300,
	top:20,
	borderStyle:Titanium.UI.INPUT_BORDERSTYLE_ROUNDED,
	rightButton:drop_button,
	rightButtonMode:Titanium.UI.INPUT_BUTTONMODE_ALWAYS
});

Please note the rightButtonMode:Titanium.UI.INPUT_BUTTONMODE_ALWAYS declaration, it makes this button visible all the time.

This is how it looks:

iPhone combobox with Titanium

Pretty sexy, isn’t it? Well we’re not done yet.

Building the modal picker

When the user focuses on the textField, the keyboard appears – so we will have to build our picker to emulate the same behaviour and to maximize the usability of our form. For this we will need a Picker and two buttons: Done and Cancel. These two buttons will be positioned in a Toolbar, again, to emulate as good as possible the keyboard behaviour.

Let’s build everything:

var picker_view = Titanium.UI.createView({
	height:251,
	bottom:0
});
 
var cancel =  Titanium.UI.createButton({
	title:'Cancel',
	style:Titanium.UI.iPhone.SystemButtonStyle.BORDERED
});
 
var done =  Titanium.UI.createButton({
	title:'Done',
	style:Titanium.UI.iPhone.SystemButtonStyle.DONE
});
 
var spacer =  Titanium.UI.createButton({
	systemButton:Titanium.UI.iPhone.SystemButton.FLEXIBLE_SPACE
});
 
var toolbar =  Titanium.UI.createToolbar({
	top:0,
	items:[cancel,spacer,done]
});
 
var picker = Titanium.UI.createPicker({
		top:43
});
picker.selectionIndicator=true;
 
var picker_data = [
	Titanium.UI.createPickerRow({title:'John'}),
	Titanium.UI.createPickerRow({title:'Alex'}),
	Titanium.UI.createPickerRow({title:'Marie'}),
	Titanium.UI.createPickerRow({title:'Eva'}),
	Titanium.UI.createPickerRow({title:'James'})
];
 
picker.add(picker_data);
 
picker_view.add(toolbar);
picker_view.add(picker);

The code is a little long but is not rocket science. Some stuff to talk about though:

  • Everyting is wrapped inside a view – picker_view – because we will have to animate like the keyboard does, so it’s faster to animate one element only.
  • The height of picker_view is the height of the toolbar (43px) + the height of the picker (208px). How do I know this? I just used a ruler ūüėÄ

The combobox interface looks like this:

picker Titanium for combobox

Creating the picker animation

We also need to create 2 animations: slide_in and slide_out. We will animate the bottom property of the picker_view. We will need to start with the picker_view off the screen, so we will build it with:

 bottom:-251

instead of 0 as it was initially.

var slide_in =  Titanium.UI.createAnimation({bottom:0});
var slide_out =  Titanium.UI.createAnimation({bottom:-251});

The logic behind the animations is this:

  • The user focuses the textField – the keyboard appears ( it’s done by the OS , no worries here) and if the picker_view is visible we need to hide it.
  • The user clicks the rightButton – we need to hide the keyboard and show the picker_view.

Here is the code:

my_combo.addEventListener('focus', function() {
	picker_view.animate(slide_out);
});
 
drop_button.addEventListener('click',function() {
	picker_view.animate(slide_in);
	my_combo.blur();
});
 
cancel.addEventListener('click',function() {
	picker_view.animate(slide_out);
});

I also added the click event on the cancel button to hide the picker_view.

Filling the textField with the picker’s value

The only thing we have left is to actually put the value of the picker in the my_combo textField when the user clicks the done button and hide the picker_view.

done.addEventListener('click',function() {
	my_combo.value =  picker.getSelectedRow(0).title;
	picker_view.animate(slide_out);
});

The getSelectedRow method of the picker is returning the selected row, and we use its title. The getSelectedRow argument is the index of the columns in the picker, and since we have only one, this is 0.

Download the project

The Resource folder of the project can be downloaded from here.

Everything is MIT licensed, but as usual, spread the word ūüôā

We have an update

@CJ_Reed used this tutorial “to produce multiple selection type data entry in a single window.”
Here is how it looks like:
to produce multiple selection type data entry in a single window.
You can take a look at his code here.
Great work!

Check the Spanish version of this post:
Haciendo una lista de opciones desplegables en Titanium Appcelerator ‚Äď C√≥digo y V√≠deo

Create a countdown timer with Titanium Appcelerator

In this post we will try to show you how to make a countdown timer using Titanium Appcelerator for Iphone or Android applications.

First we will create an OOP countDown object that can be used independently in the background of the application and then we will connect it with some interface elements.

The countDown object

To have functional a countdown timer we’ll need to declare some properties and some methods.

As properties we will set:

time:{ m : minutes, s : seconds },
total_seconds : m*60+s

I think this is pretty clear, time is an object with minutes and seconds and total_seconds contains the number of seconds until we reach 00:00.

We will need to set methods that will allow us to:

  • set a time to count from
  • stop the timer
  • start it.

We also ned to set some callback functions that will be executed on each tick of the timer   Рfn_tick Рand one that will execute when the timer reaches 00:00 named fn_end.

We won’t make a callback for start because we know when this occurs we can trigger it by ourselves.

The countDown timer will look like this:

var my_timer = new countDown( minutes, seconds, fn_tick, fn_complete);

on this we will be able to apply

my_timer.set( minutes, seconds );
my_timer.start();
my_tmer.stop();

Below is the code that defines the countDown (pretty simple).

var countDown =  function( m , s, fn_tick, fn_end  ) {
	return {
		total_sec:m*60+s,
		timer:this.timer,
		set: function(m,s) {
			this.total_sec = parseInt(m)*60+parseInt(s);
			this.time = {m:m,s:s};
			return this;
		},
		start: function() {
			var self = this;
			this.timer = setInterval( function() {
				if (self.total_sec) {
					self.total_sec--;
					self.time = { m : parseInt(self.total_sec/60), s: (self.total_sec%60) };
					fn_tick();
				}
				else {
					self.stop();
					fn_end();
				}
				}, 1000 );
			return this;
		},
		stop: function() {
			clearInterval(this.timer)
			this.time = {m:0,s:0};
			this.total_sec = 0;
			return this;
		}
	}
}

And now to use it in our code we will do something like this:

var my_timer = new countDown(1 , 5 ,
	function()	{
		//something here...
	},
	function() {
		// something here...
	}
);
 
my_timer.start();

Ok, the above example is useless, we will need to display the current time on each tick of the countdown times (so on each second) and at the end we’ll have to alert the user when we reached 00:00.

We will also need some interface elements to access the countdown methods and to display the current time.

For this we will create a label named display_lbl, that will show the time and also 3 buttons : set_btn , start_btn and stop_btn.

Creating the code is pretty simple so I won’t put the code here but you will be able to take a look at it downloading the countdown project.

What is most important is to connect the interface with the countdown timer.

So we create the timer and set the fn_tick and fn_end functions

var my_timer = new countDown(5,30, 
		function() {
			display_lbl.text = my_timer.time.m+" : "+my_timer.time.s;
		},
		function() {
			alert("The time is up!");
		}
	);

And this is how we connect the buttons with my_timer

 
set_btn.addEventListener('click',function(){
	display_lbl.text = "5 : 30";
	my_timer.set(5,30);
});
 
stop_btn.addEventListener('click',function(){
	my_timer.stop();
});
 
start_btn.addEventListener('click',function(){
	my_timer.start();
});

As you see we also set the label’s text to the initial value when we set the timer because otherwise we’ll loose the first second. We do this here to keep the timer object clean of any external interaction so we can use it even without an interface.

This is how the final project looks like

Countdown timer with Appcelerator

Please keep in mind that this is just a simple example and we don’t have a control mechanism to detect when the user stopped the timer or it reached by itself 00:00 – but you can add it as an exercise ūüôā

You can download the Resources folder of the project from here.

Everything is MIT licensed and you can use it in any application you want to, but spreading the word would be nice.

Check the Spanish version of this post:
Crear un temporizador regresivo con Titanium Appcelerator

iPhone tooltip with Titanium

Create a nifty tooltip in Titanium

In this post I will show how to create a tooltip to those that are using Titanium to develop their iPhone apps.
Sometimes when we set a button with an icon – lets say in navbar – a simple icon is not enough to make the user understand what the button is supposed to do.

For example this one:

What would the rightNavButton do ? The application is an ebook reader – if this helps, but I’m sure it will not….

What about this:

Now you know that by hitting this button you can continue your reading – in case something took you out from the chapter, like ¬†changing a setting, or answering the phone or whatever…

So let’s start.

The tooltip is a simple view with the tip image set as background:

var lasttipView =  Titanium.UI.createView({
width:205,
height:57,
backgroundImage:"img/bubble.png",
top:0,
right:3
});

The “Continue reading” is a simple label added to this view

var lasttipLabel =  Titanium.UI.createLabel({
text:'Continue reading',
color:'#fff',
width:205,
height:34,
top:16,
font:{
fontFamily:'Helvetica Neue',
fontSize:13,
fontWeight:'bold'
},
textAlign:'center'
});
 
lasttipView.add(lasttipLabel);

and the index window contains the tip view

index_win.add(lasttipView);

I supposed we already have the index_win created.

Now when we open the index_win the tooltip will be there and the user will know what the rightNavButton does. But if the tooltip stays there it becomes annoying so we need to find a way to hide it. I choose to hide it when the user clicks the button by using a smooth fadeout.

The code below creates an animation and attaches it to the click event.

var anim_out = Titanium.UI.createAnimation();
anim_out.opacity=0;
anim_out.duration = 250;
 
 
last_read =  Titanium.UI.createButton({
image:"img/tag1.png"
});
 
 
last_read.addEventListener('click', function() {
lasttipView.animate(anim_out);
});
 
index_win.setRightNavButton( last_read );

Ok, here is the button code too but for simplicity I removed some parts that actually display the chapter and trigger other functions.

That’s all. Pretty simple, isn’t it ?

PS. You can use the bubble image in your apps if you want, only just let me know – and if you are curious about the app here it is:
Youth, by Isaac Asimov iPhone ebook.

Check the Spanish version of this post:
Crear una ingeniosa herramienta de notificación en Titanium

Custom table rows with Titanium

Custom row for TableView in Appcelerator Titanium

In this post  I will try to explain how to create custom rows for TableViews using Titanium Mobile.

If you don’t know what Titanium is about, ¬†take a look here.¬†I suppose you already know how to setup and start a Titanium project so I’ll show only how to create a custom row.

By default a TableView will let you create a row that can have: the left image, the title and the row type decorator set. The next code is an example of the standard data that needs to be passed to a TableView.

var RegData = [
 
{ leftImage:'es.png', title:"Spain", hasChild:true },
{ leftImage:'gb.png', title:"United Kingdom", hasChild:true },
{ leftImage:'us.png', title:"United States", hasChild:true },
{ leftImage:'fr.png', title:"France", hasChild:true }
];
 
var TheTable = Titanium.UI.createTableView({
data:RegData
});

And the result is this:

Ok, we would like to add more data to a row, maybe something like this:

This will require to build the row “by hand”. So we need to add a 2 imageViews, the flag and the trend, and ¬†labelViews for the country and the percent . We also need to change the data array of course.

var CustomData = [
{ flag:'es.png', country:"Spain", trend:'up.png', percent:'28%' ,hasChild:true },
{ flag:'gb.png', country:"United Kingdom", trend:'down.png', percent:'-3%', hasChild:true },
{ flag:'us.png', country:"United States", trend:'up.png', percent:'8%', hasChild:true },
{ flag:'fr.png', country:"France", trend:'down.png', percent:'-40%', hasChild:true }
];

We create a data variable as an array that will hold the row objects generated.

var data=[];

then we walk through the CustomData array, create  a new row , the imageViews and labels and add them to the row.

for (var i = CustomData.length - 1; i <= 0; i--) {
var row = Titanium.UI.createTableViewRow();
 
var flag =  Titanium.UI.createImageView({
url:CustomData[i].flag,
width:32,
height:32,
left:4,
top:2
});
 
var country = Titanium.UI.createLabel({
text:CustomData[i].country,
font:{fontSize:16,fontWeight:'bold'},
width:'auto',
textAlign:'left',
top:2,
left:40,
height:16
});
 
var percent =  Titanium.UI.createLabel({
text:CustomData[i].percent,
font:{fontSize:12,fontWeight:'bold'},
width:'auto',
textAlign:'left',
bottom:0,
left:60,
height:12
});
 
var trend =  Titanium.UI.createImageView({
url:CustomData[i].trend,
width:16,
height:16,
right:10
});
 
row.add(flag);
row.add(country);
row.add(percent);
row.add(trend);
row.hasChild=CustomData[i].hasChild;
 
row.className = 'coutry_row';
 
data.push(row);
};

As you see we also add a className to the row to improve the rendering performance, as the iPhone will reuse the row template with every new data when rendering the table.

The obtained result is this:

You can download the complete Titanium project from here. You will have to create a new project in Titanium and replace the resource folder with the one in the archive.

Let me know your thoughts.

Check the Spanish version of this post:
Como crear filas personalizadas para TableViews usando Titanium Móvil