Tag Archives: Iphone

Crear un temporizador regresivo con Titanium Appcelerator

En este post trataremos de mostrarle cómo hacer un temporizador regresivo usando Titanium Appcelerator para su aplicación en Iphone o Android.

Primero crearemos un objeto OOP countDown que puede ser usado independientemente en segundo plano en la aplicación, el cual, conectaremos con algunos elementos de interface.

El Objeto countDown

Para tener funcional el temporizador regresivo, necesitaremos declarar algunas propiedades y algunos métodos.

Como propiedades colocaremos :

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

Creo que es bastante claro, “time” es un objeto con minutos y segundos y segundos_totales (total_seconds) contiene el número de segundos hasta que alcancemos 00:00

Necesitaremos colocar métodos que nos permitan:

  • Ajustar un tiempo en forma de contador.
  • Parar el temporizador.
  • Iniciarlo.

Además necesitamos colocar algunas funciones de llamadas que serán ejecutadas en cada tick del temporizador – fn_tick – y una que se ejecutará cuando el temporizador alcance 00:00 denominada fn_end.

No haremos una llamada para el inicio porque sabemos cuando ocurre esto y podemos lanzarlo por nosotros mismos.

El temporizador countDown se verá como esto:

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

Y seremos capaces de aplicar:

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

Debajo se encuentra el código que define el countDown (bastante 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;
		}
	}
}

Y ahora, para usarlo en nuestro código, haremos algo como esto:

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

Ok, el ejemplo de arriba es inútil, necesitaremos mostrar el tiempo actual en cada tick del contador (osea, en cada segundo) y al final, tendremos una alerta al usuario cuando se alcance 00:00

Adicionalmente, necesitaremos algunos elementos de interface para acceder a los métodos del contador para mostrar el tiempo actual.

Para esto, crearemos una etiqueta llamada display_lbl, que mostrará el tiempo y además 3 botones: set_btn, start_btn y stop_btn.

Crear el código es bastante simple, así que no les pondré el código aquí, pero puede echarle un vistazo cuando bajen el proyecto del temporizador regresivo.

Lo que es mas importante es conectar la interface con el contador del temporizador.

Así que creamos el temporizador y le colocamos las funciones fn_tick y fn_end

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!");
		}
	);

Y asi es como conectaremos los botones con 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();
});

Como puede ver, también le colocamos a la etiqueta un valor inicial cuando iniciamos el temporizador porque de otra manera, perderemos el primer segundo. Hacemos esto aquí para mantener el objeto del temporizador libre de interacción externa y de esta manera podremos usarlo incluso sin interface.

Así es como se verá el proyecto final:

Countdown timer with Appcelerator

Por favor, tenga en mente que este es solo un ejemplo simple y no tenemos mecanismos de control para detectar cuando el usuario para el temporizador o cuando alcance 00:00 por sí mismo – pero se lo pueden añadir como ejercicio.

Pueden bajar el directorio de Recursos desde aquí.

Todo lo demás tiene licencia MIT y puede usarlo en cualquier aplicación que quiera, no obstante, si difunde la palabra sería agradable.

Haciendo una lista de opciones desplegables en Titanium Appcelerator – Código y Vídeo

Algunas veces necesitamos una verdadera lista de opciones desplegables (combobox) para nuestros proyectos pero el SDK del Iphone no tiene uno que sea nativo (al menos que yo sepa) y por supuesto tampoco lo tiene Titanium.

Así que construiremos uno. Un “verdadero” combobox para iPhone y iPad que permita al usuario usar el mismo campo de texto para introducir textos arbitrarios o seleccionar un valor desde un elemento UIPicker.

Actualizado con capturas de pantalla de @CJ_Reed’s screenshot y el código del final del tutorial.

Vemos el vídeo primero, luego haremos el trabajo:

Ok, qué necesitamos para este combobox para el iPhone?

Primero que todo, necesitamos un campo de texto textField que acepte entradas del usuario. Titanium le permite colocar un botón a la izquierda (leftButton) y un botón a la derecha (rightButton) para este textField mientras se construye. Así que tomaremos ventaja de esto y crearemos un textField de la siguiente manera:

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
});

Nada especial, un textField regular con una pequeña referencia para el usuario que desaparecerá cuando el textField tenga un valor.

Ahora necesitamos crear el rightButton para él.

Usaremos los botones del sistema provistos por Apple(Titanium.UI.iPhone.SystemButton.DISCLOSURE) sólo que lo rotaremos 90 grados para que sirva a nuestros propósitos. Este es el código que crea el rightButton y la transformación aplicada al mismo.

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

Ahora que tenemos el rightButton que necesitamos, el constructor del textField se convierte en:

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
});

Note la declaración rightButtonMode:Titanium.UI.INPUT_BUTTONMODE_ALWAYS , esto hace que el botón sea visible todo el tiempo.

Así es como se ve:

iPhone combobox with Titanium

Bastante sexy verdad?, bueno, aún no hemos terminado.

Construir el selector modal

Cuando el usuario coloque el foco en el textField, el teclado aparece – así que tendremos que construir nuestro selector para emular el mismo comportamiento y maximizar la usabilidad de nuestro formulario. Para esto necesitaremos un Selector y dos botones: “Done” y “Cancel”. Estos dos botones posicionaremos en una barra de herramientas, nuevamente, para emular de la mejor manera posible, el comportamiento del teclado.

Construyamos todo:

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);

Este código es un poco largo, pero no es ciencia de cohetes, algunas cosas sobre las que conversar:

  • Todo está envuelto en una vista – picker_view – porque tendremos que animarlo como lo hace el teclado, así que es mas rápido animar sólo un elemento.
  • La altura del picker_view es la altura de la barra de herramientas (43px) + la altura del selector (208px). Cómo sé esto? Usé una regla. 😀

La interfaz del combobox se verá así:

picker Titanium for combobox

Creando la animación del selector

Adicionalmente, necesitamos crear dos animaciones: slide_in y slide_out. Animaremos la propiedad bottom del picker_view. Necesitamos comenzar con el picker_view fuera de la pantalla, por lo tanto, lo construimos de la siguiente manera:

 bottom:-251

En vez de cero como tenia inicialmente.

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

La lógica detrás de la animación es esta:

  • El usuario coloca el foco sobre el textField – el teclado aparece (es hecho por el SO, no hay de que preocuparse aquí), y si el picker_view está visible, necesitamos ocultarlo.
  • El usuario hace click en el rightButton – necesitaremos ocultar el teclado y mostrar el picker_view

Aquí está el código:

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);
});

Además añadí el evento para cuando hagan click en el botón cancel para ocultar el picker_view.

Llenar el textField con el valor del selector

Lo único que nos queda por hacer es colocar el valor del selector en el textField de my_combo cuando el usuario haga click en el botón done y ocultar el pick_view.

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

El método getSelectedRow del selector retorna la fila seleccionada, y nosotros usaremos este titulo. El argumento del getSelectedRow es el índice de la columna del selector, y ya que sólo tenemos uno, es 0.

Bajar el proyecto

El directorio de recursos del proyecto puede ser bajado aquí.

Todo lo demás tiene licencia MIT y como es usual, difundan la palabra 🙂

Tenemos una actualización

@CJ_Reed só este tutorial para “producir tipos de datos de selección múltiple en una sola ventana”

Así es como se ve:

producir tipos de datos de selección múltiple en una sola ventana

Puede echarle un vistazo al código aquí.

Estupendo trabajo!