Los recursos ayudan a la localización. Por ejemplo, podemos tener valores para strings que cambien en función del idioma configurado en el terminal. Los recursos Android generalizan esta idea para cualquier configuración del dispositivo, el idioma es tan solo otra configuración más. Otro ejemplo de cambios de configuración se dá cuando el dispositivo cambia de posición (de vertical a horizontal o viceversa). El modo vertical se suela llamar portrait y el horizontal landscape.

Android permite elegir distintas configuraciones de layout basandose en el tipo de layout. Y ambos tendrán el mismo ID de recurso. Esto se consigue usando directorios diferentes para cada configuración. Vamos a verlo con un ejemplo:



/res/layout/main_layout.xml
/res/layout-port/main_layout.xml
/res/layout-land/main_layout.xml

Aunque hay tres archivos layout separados, solo se generará un único ID para ellos en R.java. Este ID será de la forma R.layout.main_layout

Sin embargo, cuando recuperemos el layout correspondiente a este ID, obtendremos el layout apropiado para la configuración actual del dispositivo.

En el ejemplo anterior, las extensiones de los directorios -port y -land se llaman configuration qualifiers. Estos clasificadores (qualifiers), se tienen que separar del directorio original añadiendo un guión (-) a su nombre. Los recursos para los que especificamos estos clasificadores de configuración se llaman recursos alternativos. Los recursos almacenados en el directorio de recursos sin los clasificadores de configuración se llaman recursos por defecto.

En la siguiente lista se muestran los clasificadores de configuración disponibles:

Con los clasificadores mostrados arriba, podemos crear directorios de recursos como los siguientes:

/res/layout-mcc312-mnc222-en-rUs
/res/layout-ldpi
/res/layout-hdpi
/res/layout-car

Para saber nuestra localización actual podemos ejecutar una aplicación que viene instalada en el emulador android. La encontramos en el menú de aplicaciones y se llama Custom Locale.

Dado un ID de recurso, Android usa un algoritmo para elegir el adecuado. Si deseas saber más acerca de este tema puedes visitar la siguiente dirección http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources, pero voy a dar unas reglas básicas.

La primera regla es que los clasificadores mostrados arriba están en orden de precedencia. Veamos un ejemplo de como funciona la precedencia:

/res/layout/main_layout.xml
/res/layout-port/main_layout.xml
/res/layout-en/main_layout.xml

En este listado, el archivo main_layout.xml está disponible para dos variaciones posibles. Una variación para el idioma y otra para la orientación. Veamos que layout se selecciona si tenemos el dispositivo en vertical.

Incluso si el dispositivo está en vertical, Android va a elegir el layout que reside en la carpeta layout-en, ya que en la lista de clasificadores que vimos anteriormente el idioma está por delante del modo portrait (Vertical). En la dirección dada anteriormente se encuentra todo esto explicado más detalladamente.

Ahora vamos a ver algunas reglas de precedencia con unos ejemplos de recursos strings. Pero los recursos string son recursos basados en ids individuales, mientras que los ids de layout se basan en los archivos. Para probar la precedencia con recursos string, vamos a definir cinco Ids para las siguientes variaciones:default, en, en_us, port, en_port. Los cinco recursos son los siguientes:

El siguiente código muestra las variaciones del directorio values:

// values/string.xml
<resources xmlns="http://schemas.android.com/apk/res/android">
   <string name="teststring_all">teststring in root</string>
   <string name="t1_enport">t1 in root</string>
   <string name="t1_1_en_port">t1_1 in root</string>
   <string name="t2">t2 in root</string>
   <string name="testport_port">testport in root</string>
</resources>
 
// values­en/string_en.xml
<resources xmlns="http://schemas.android.com/apk/res/android">
 <string name="teststring_all">teststring­en</string>
 <string name="t1_enport">t1_en</string>
 <string name="t1_1_en_port">t1_1_en</string>
</resources>
 
// values­en­rUS/string_en_us.xml
<resources xmlns="http://schemas.android.com/apk/res/android">
<string name="teststring_all">test­en­us</string>
</resources>
 
// values­port/string_port.xml
<resources xmlns="http://schemas.android.com/apk/res/android">
 <string name="teststring_all">test­en­us­port</string>
 <string name="testport_port">testport­port</string>
 <string name="t1_enport">t1_port</string>
 <string name="t1_1_en_port">t1_1_port</string>
</resources>
 
// values/string_en_port.xml
<resources xmlns="http://schemas.android.com/apk/res/android">
 <string name="teststring_all">test­en­port</string>
 <string name="t1_1_en_port">t1_1_en_port</string>
</resources>

El listado siguiente muestra el archivo R.java para estos recursos:

public static final class string {
        public static final int t1_1_en_port=0x7f070004;
        public static final int t1_enport=0x7f070003;
        public static final int t2=0x7f070005;
        public static final int testport_port=0x7f070006;
        public static final int teststring_all=0x7f070002;
}

Como se aprecia, aunque hemos definido muchos strings, solo se han generado cinco IDs. A continuación se describe el comportamiento para cada string, que se ha probado con en_US y el modo portrait:

El SDK de Android tiene algoritmos más detallados aún, sin embargo, con este ejemplo se ha mostrado lo esencial. La clave está en darse cuenta de la precedencia de cada variación sobre otra. A continuación, para aquellos que deseen ampliar información dejo unas URLs de referencia:

Referencias