viernes, 28 de enero de 2011

El equivalente al onTextChange en un EditText [Android]

En muchos lenguajes de programación estamos acostumbrados a encontrar un evento del tipo onTextChange que nos permita realizar una acción a medida que el usuario introduce o modifica el contenido de un campo de texto. Esta funcionalidad es la que nos permitiría, por ejemplo, implementar un contador que le diga al usuario cuantos caracteres disponibles le quedan a medida que va tecleando un tuit o un SMS. Pues bien, implementar esta funcionalidad en Android es igualmente posible, solo que de una forma ligeramente diferente a lo que podemos estar acostumbrados.

En mi caso, para la implementaciön para Android de Aleatorizr lo que quería era inhabilitar un botón siempre que el campo de texto estuviese vacío o su contenido fuese 0. Esta implementación se consigue utilizando el método addTextChangedListener y la clase TextWatcher. Este sería el código.

this.edit_limite = (EditText) findViewById(R.id.edit_limite); this.edit_limite.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub Button btn_alea = (Button) findViewById(R.id.btn_alea); if (s.length()==0){ btn_alea.setClickable(false); btn_alea.setEnabled(false); }else { Integer valor = new Integer(s.toString()); if(valor == 0){ btn_alea.setClickable(false); btn_alea.setEnabled(false); } else { btn_alea.setClickable(true); btn_alea.setEnabled(true); } } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub } });

Enlaces:

miércoles, 5 de enero de 2011

Prevenir el cierre de ventana / pestaña en los navegadores [javascript]

Esto es útil para prevenir que el usuario cierre sin querer el navegador o la pestaña, durante una tarea se puede añadir el evento:

window.onbeforeunload = function(e){
e.returnValue='No has guardado los cambios, ¿Quieres salir sin guardar?';
return 'No has guardado los cambios, ¿Quieres salir sin guardar?';
}


Cuando la tarea crítica ha terminado, se puede quitar el evento.

lunes, 29 de noviembre de 2010

Crear un componente personalizado desde XML [Android]

Los componentes personalizados de Android nos permiten personalizar elementos de interfaz, bien modificándolos o bien agrupando varios en un único componente que podamos reutilizar. La documentación de Android denomina a este tipo de controles compuestos a su vez de varios controles estándar de Android Compound Components. Se explica cómo construir uno de estos controles en el código Java de una nueva clase, pero no queda muy claro cómo podríamos construir el componente si quisieramos utilizar uno de los ficheros de interfaz XML.

Para hacerlo, empezaríamos definiendo la interfaz en un fichero XML, que en mi caso sería /res/layout/elementos_lista.xml. En este caso vamos a hacer algo sencillo: un cuadro de texto con un botón.

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_width="fill_parent"> <LinearLayout android:id="@+id/LinearLayout01" android:layout_width="fill_parent" android:layout_height="wrap_content"> <EditText android:layout_height="50px" android:id="@+id/edit_persona" android:layout_width="fill_parent" android:layout_weight="1"></EditText> <Button android:id="@+id/btn_agenda" android:layout_height="50px" android:layout_width="fill_parent" android:layout_weight="3" android:text="Agenda"></Button> </LinearLayout> </LinearLayout>

Con esto creamos una clase en nuestra carpeta src que extienda a la clase LinearLayout y desde la que cargaremos ese fichero XML en su constructor. Como queremos que el botón ejecute una acción (en este caso imprimir algo por pantalla) definimos también un OnClickListener con la manejadora del click sobre el botón.

package ocode.apps.aleatorizr; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Toast; public class ElementosListaComponent extends LinearLayout { public OnClickListener agendaHandler = new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(v.getContext(), "click en el botón agenda", Toast.LENGTH_SHORT).show(); } }; public ElementosListaComponent(Context context) { super(context); } public ElementosListaComponent(Context context, AttributeSet attr){ super(context,attr); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); LinearLayout vistaCompuesta = (LinearLayout) inflater.inflate(R.layout.elementos_lista, this); Button btn_agenda = (Button) vistaCompuesta.findViewById(R.id.btn_agenda); btn_agenda.setOnClickListener(agendaHandler); } }

Lo importante de este código está ocurriendo en el segundo constructor, que por medio de LayoutInflater procesa el código XML de la interfaz del componente para que lo tengamos accesible para ser utilizado desde cualquier otra vista del programa. Con esto hecho, si quisiesemos utilizarlo en otro layout sólo tendremos que abrir dicho layout y utilizar el siguiente código:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:text="Selecciona uno" android:id="@+id/txt_pic" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> <ocode.apps.aleatorizr.ElementosListaComponent android:layout_width="fill_parent" android:layout_height="wrap_content"> </ocode.apps.aleatorizr.ElementosListaComponent> </LinearLayout>

martes, 23 de noviembre de 2010

Configurar EditText para que utilice el teclado numérico [Android]

Cuando sabemos que en un campo de texto de tipo EditText sólo puede recibir un número, nos puede interesar configurarlo para que cargue sólo el teclado numérico en lugar del teclado completo. Para hacer esto sólo hay que definir el EditText añadiendo los siguientes atributos:

<EditText 
   android:numeric="integer"
   android:inputType="number">
</EditText>

Referencias en la documentación de Android:

martes, 16 de noviembre de 2010

URL Encoding en Objective-C [Receta iPhone y iPad]

Si necesitamos comunicarnos con algún servicio web enviándole datos es muy probable que tratemos de formar la url a partir de una cadena de caraceteres:


NSString *urlString = [NSString stringWithFormat:@"http://servicio/parametro1/%@/",
parametro];

Cuidado con esto. Te puedes encontrar con que el servicio devuelva un BAD REQUEST debido a que no entiende el contenido de los parámetros.

Solución

La solución radica en formar la url así


NSURL *theURL = [[NSURL alloc] initWithScheme:@"http" host:@"servicio"
path:[NSString stringWithFormat:@"/%@",parametro]];


En ese caso la codificación a porcentajes la hará automáticamente.

jueves, 11 de noviembre de 2010

Cargar una imagen desde una Url [Receta iPhone y iPad]

Hasta que los desarrolladores del iOS SDK se dignen a hacer una función del tipo


[UIImage imageFromURL:url];

nos tendremos que conformar con esto:

Solución


NSURL *url = [NSURL URLWithString:urlImagen];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
//Hacemos cosas con la imagen...
[img release];

Explicación

Creamos un objeto url que se lo pasamos al método de NSData capaz de obtener datos desde una url. Como UIImage cuenta con un método capaz de crear una imagen desde un NSData le pasamos la imagen descargada.

Cómo cambiar el fondo del UISearchBar [Receta iPhone y iPad]

Inauguramos este blog dedicado a recopilar pequeños trozos de código que vamos necesitando a medida que desarrollamos aplicaciones para iPhone, Android, iPad o Windows Phone 7.

Cambiando el fondo al UISearchBar

El UISearchBar es un elemento de interfaz que ofrece el SDK de iOS. Cambiar el fondo (no el tint sytle) puede suponer un engorro.

Solución


UILabel *lbl = [[UILabel alloc]init];
lbl.frame = searchbar.frame;
lbl.backgroundColor = [UIColor cyanColor];
[self.searchbar insertSubview:lbl atIndex:1];
[lbl release];

Explicación

Creamos un vista (en este caso un UILabel), le asignamos las dimensiones y posición de la barra de búsqueda y lo insertamos por encima de la primera vista.

Cuidado

No es conveniente hardcodear el índice de las vistas porque puede variar de una versión a otra del SDK. Puede que a la gente de Cupertino les de por cambiar la posición de cada subvista.