Bug de RelativeLayout con fill_parent

Cuando se utiliza de altura y ancho “fill_parent” en un RelativeLayout, es probable que le de algunas sorpresas.

Si es utilizado directamente en un archivo de layout, es probable que no de mucho problema, pero a la hora de crear componentes a base de este layout (utilizando el LayoutInflater) podrá notar que se comporta muy diferente. Particularmente con las alturas “ajustables”.

Buscando la razón me encontre este ticket en los bug reports de Android: http://code.google.com/p/android/issues/detail?id=1394 donde básicamente describen este problema y nos dan la solución. Utilizar altura y ancho fijos.

El siguiente layout

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="50dip"
  android:layout_height="50dip"
>
	<RelativeLayout
	  android:background="#FFFFFF"
	  android:layout_width="fill_parent"
	  android:layout_height="fill_parent">
	  
	  
	  <TextView 
	  	android:text="1"
	  	android:textColor="#FF0000"
	  	android:layout_alignParentTop="true"
	  	android:layout_alignParentLeft="true"
	  	android:layout_width="wrap_content" 
	  	android:layout_height="wrap_content" />
	  <TextView 
	  	android:text="2"
	  	android:textColor="#FF0000"
	  	android:layout_alignParentTop="true"
	  	android:layout_alignParentRight="true"
	  	android:layout_width="wrap_content" 
	  	android:layout_height="wrap_content" />
	  <TextView 
	  	android:text="3" 
	  	android:textColor="#0000FF"
	  	android:layout_alignParentBottom="true"
	  	android:layout_alignParentRight="true"
	  	android:layout_width="wrap_content" 
	  	android:layout_height="wrap_content" />
	  <TextView 
	  	android:text="4" 
	  	android:textColor="#0000FF"
	  	android:layout_alignParentBottom="true"
	  	android:layout_alignParentLeft="true"
	  	android:layout_width="wrap_content" 
	  	android:layout_height="wrap_content" />
	</RelativeLayout>
</FrameLayout>

Da como resultado este posicionamiento, normal, en el preview del layout en Eclipse.

Hemos utilizado un GridView con 10 Views que utilizan el layout anterior. Pero en vez de mostrarlo similar que en el preview, se muesta de la siguiente manera en un teléfono:

Como se citó anteriormente, al momento de ponerle altura fija directamente en la configuración del RelativeLayout, se resuelve el problema.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
>
	<RelativeLayout
	  android:background="#FFFFFF"
	  android:layout_width="50dip"
	  android:layout_height="50dip">
	  
	  
	  <TextView 
	  	android:text="1"
	  	android:textColor="#FF0000"
	  	android:layout_alignParentTop="true"
	  	android:layout_alignParentLeft="true"
	  	android:layout_width="wrap_content" 
	  	android:layout_height="wrap_content" />
	  <TextView 
	  	android:text="2"
	  	android:textColor="#FF0000"
	  	android:layout_alignParentTop="true"
	  	android:layout_alignParentRight="true"
	  	android:layout_width="wrap_content" 
	  	android:layout_height="wrap_content" />
	  <TextView 
	  	android:text="3" 
	  	android:textColor="#0000FF"
	  	android:layout_alignParentBottom="true"
	  	android:layout_alignParentRight="true"
	  	android:layout_width="wrap_content" 
	  	android:layout_height="wrap_content" />
	  <TextView 
	  	android:text="4" 
	  	android:textColor="#0000FF"
	  	android:layout_alignParentBottom="true"
	  	android:layout_alignParentLeft="true"
	  	android:layout_width="wrap_content" 
	  	android:layout_height="wrap_content" />
	</RelativeLayout>
</FrameLayout>

Dando como resultado, el layout esperado:

Otra nota curiosa, es que esto solo es posible verlo en telefonos reales, ya que en los emuladores este problema no es posible replicarlo. Personalmente había visto este problema ocurrir solo en Android 2.1 (Eclair), pero a la hora de preparar este ejemplo, lo pude replicar tanto en un telefono con Eclair como con FroYo.

Fechas validas y java.util.Date

Pues leyendo el Javadoc de la clase java.util.Date, me encontre la sorpresa de que uno puede crear fechas “invalidas”, por ejemplo Diciembre 32. Para bien o para mal, cuando se crea el objecto Date (usando DateFormat por ejemplo) en vez de generar una excepción, lo que hace Java con Diciembre 32, es convertirlo en Enero 1. Puede que en algunos casos, esto sirva de mucho, y evite un dolor de cabeza, al hacer esta conversión de manera automática. EL problema se da cuando ocupamos validad que la fecha ingresada sea válida en todos los sentidos. Me encontre por ahi un codigo que nos ayudaria a resolver el problema, la verdad la solución es bastante sencilla.

     public Date getDate() {
        // Fechas serian de la forma 20091231
        DateFormat formatter = new SimpleDateFormat("yyyyMMdd");

        Date myDate = formatter.parse("20091232");

        // myDate ahora seria 2010-01-01, al compararla con la fecha original 
        // nos damos cuenta que vario, es decir ocupo ajuste. Podemos decir 
        // que la fecha ingresada no es valida y tirar una excepción
        if (! formatter.format(myDate).equals("20091232")){
            throw new ParseException("Date is invalid",0);
        }
        return myDate;

Esta es una manera ingeniosa de resolver este problema. Si tienen otras soluciones, agradeceria que las agregaran en sus comentarios. -fr4gus