viernes, 26 de septiembre de 2014

Accediendo a los recursos

Cada recurso en nuestra aplicación, se identifica a través de un ID de recurso. Se trata de un número entero único que se encuentra definido dentro de la clase especial R. Cada vez que la aplicación es compilada, la herramienta aapt generará automáticamente la clase R con todos los IDs asociados a los archivos contenidos en la carpeta res/ de nuestro proyecto. Por cada tipo de recurso se creará una subclase de la clase R (por ejemplo, R.drawable para recursos de tipo imagen), y por cada recurso se creará una constante de tipo entero (por ejemplo, R.drawable.icon, línea 9). Esta variable será la que utilizaremos para acceder al recurso.

La clase especial R:
public final class R {
    public static final class attr {
    }
    public static final class dimen {
        public static final int activity_horizontal_margin=0x7f040000;
        public static final int activity_vertical_margin=0x7f040001;
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int action_settings=0x7f080002;
        public static final int listView=0x7f080001;
        public static final int textView=0x7f080000;
    }
    public static final class layout {
        public static final int activity_my=0x7f030000;
    }
...
}

La clase R es gestionada de manera automática y no tendremos que modificar o consultar su contenido. El nombre asociado a un ID de recurso se construye a partir de:
  • El tipo de recurso: string, drawable, layout, etc.
  • El nombre del recurso: el nombre de su archivo sin tener en cuenta la extensión, o bien, si el recurso es un valor simple (un color o una cadena de texto, por ejemplo), usaremos el valor de su atributo android:name.

El acceso a los recursos se puede hacer de dos maneras:
  • Desde el código Java. Haremos referencia al ID de un recurso haciendo uso de la clase especial R. Por ejemplo: R.string.hello: donde string es el tipo de recurso y hello el nombre del recurso. En las APIs de Android hay multitud de métodos que son capaces de acceder a los recursos a través de su ID.
  • Desde el código XML.
  • Utilizaremos una sintaxis especial para hacer referencia a los IDs definidos en la clase R. Por ejemplo: @string/hello: donde string es el tipo de recurso y hello es el nombre del recurso. Podremos utilizar esta sintaxis en cualquier parte del archivo XML.

Accediendo desde el código Java.

Normalmente utilizaremos los IDs de recurso como argumento en los métodos. Por ejemplo, podríamos asignar a una vista de tipo ImageView la imagen res/drawable/myimage.png usando el método setImageResource() de la siguiente manera:
ImageView imageView = (ImageView) findViewById(R.id.myimageview);
imageView.setImageResource(R.drawable.myimage);
Será el método el encargado de acceder al recurso original a la hora de mostrar la imagen en la vista.

Si lo que queremos es acceder directamente a un recurso, utilizaremos la clase Resources. Podemos obtener su instancia a través del método getResources().

Sintaxis.

La sintaxis completa para hacer referencia a un recurso desde nuestro código Java sería:
[<nombre_paquete>.]R.<tipo_recurso>.<nombre_recurso>
donde:
  • <nombre_paquete> es el nombre del paquete donde el recurso se encuentra localizado (necesario solo si hacemos referencia a recursos que se encuentran en otro paquete).
  • <tipo_recurso> es el tipo de recurso (subclase de la clase especial R).
  • <nombre_recurso> es el nombre del archivo sin especificar la extensión, o bien, el valor del atributo android:name si se trata de un valor simple.

Nota. Recuerda que los corchetes ([]) en la expresión sintáctica representan opcionalidad.

Ejemplos.

// Asignamos un nuevo fondo de pantalla para la ventana actual.
getWindow().setBackgroundDrawableResource(R.drawable.my_background_image) ;

// En este caso accedemos directamente al recurso a través del objeto Resources
// ya que el método setTitle espera como argumento una cadena de texto.
getWindow().setTitle(getResources().getText(R.string.main_title));

// Asociamos la plantilla a la actividad actual.
setContentView(R.layout.main_screen);

// Set a slide in animation by getting an Animation from the Resources object.
mFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.hyperspace_in));

// Asignamos el texto de una vista TextView a partir del ID de recurso.
TextView msgTextView = (TextView) findViewById(R.id.msg);
msgTextView.setText(R.string.hello_message);

Accediendo desde el código XML.

Algunos atributos XML admiten como valor referencias a los recursos existentes en nuestra aplicación. Por ejemplo, podríamos usar un recurso de tipo string para etiquetar un botón:
<Button
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/submit" />
En el ejemplo estamos asociando al atributo android:text el valor contenido en el recurso @string/submit: "Enviar", por ejemplo.

Sintaxis.

La sintaxis completa para hacer referencia a un recursos desde nuestro código XML:
@[<nombre_paquete>:]<tipo_recurso>/<nombre_recurso>
donde:
  • <nombre_paquete> es el nombre del paquete donde se encuentra el recursos localizado (necesario solo si hacemos referencia a recursos que se encuentran en otro paquete).
  • <tipo_recurso> es la subclase de la clase R asociada al tipo de recurso.
  • <nombre_recurso> es el nombre del archivo sin especificar la extensión, o bien, el valor del atributo XML android:name si se trata de un valor simple.

Ejemplos.

Habrá casos en los que nos interese reutilizar ciertos valores simples (colores, cadenas de texto, etc) en nuestros archivos XML. Supongamos que hemos definido los siguientes valores simples dentro de la carpeta res/values/:
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <color name="opaque_red">#f00</color>
   <string name="hello">Hello!</string>
</resources>
Hemos definido dos recursos: uno de tipo color al que hemos llamado opaque_red y otro de tipo string al que hemos llamado hello. Sus valores son #f00 y Hello! respectivamente. Supongamos que dentro de nuestra plantilla, hemos definido un campo de texto y que queremos cambiar sus atributos android:textColor y android:text utilizando los valores anteriormente definidos:
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:textColor="@color/opaque_red"
    android:text="@string/hello" />
En este caso no hemos tenido que especificar el nombre del paquete a la hora de hacer referencia a los recursos puesto que éstos están asociados al paquete de nuestra aplicación. Si quisiésemos hacer referencia a un recurso definido por el sistema, tendríamos que utilizar como nombre de paquete android:
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:textColor="@android:color/secondary_text_dark"
    android:text="@string/hello" />
Nota. Es una buena práctica utilizar recursos de tipo string en nuestra interfaz de usuario. Esto nos permitirá preparar nuestra aplicación para que pueda soportar múltiples idiomas.

Desde el código XML también podremos hacer referencia a un alias de recurso. Los alias nos van a permitir la reutilización de recursos:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/other_drawable" />

Haciendo referencia a atributos de estilo.

Los atributos asociados al estilo de un elemento pueden hacer referencia a atributos asociados al tema actual. Hacer referencia a un atributo de estilo nos permitirá personalizar la apariencia de los elementos de la interfaz de una manera rápida. Para hacer referencia a un atributo de estilo, la sintaxis que utilizaremos es idéntica a la que usamos para hacer referencia a los recursos, pero en lugar de utilizar el carácter @, utilizaremos el carácter ? (el tipo de recurso attr es opcional). Por ejemplo:
?[<nombre_paquete>:][<tipo_recurso>/]<nombre_recurso>
En el siguiente ejemplo hacemos referencia a un atributo de estilo asociado al sistema (textColorSecondary):
<EditText id="text"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="?android:textColorSecondary"
    android:text="@string/hello_world" />
En el ejemplo le estamos diciendo a Android que utilice como color para el texto de nuestro campo, el color correspondiente al atributo de estilo textColorSecondary que utiliza el sistema.

Como a partir del contexto se puede deducir que estamos accediendo al valor de un atributo de estilo (attr), no hace falta especificar la sintaxis completa: ?android:attr/textColorSecondary.

Accediendo a los recursos propios de Android.

Todos los recursos que el sistema utiliza para su funcionamiento, los tendremos a nuestro alcance desde nuestras aplicaciones: imágenes, iconos, estilos, plantillas, etc. Para acceder a estos recursos, utilizaremos como nombre de paquete android. Por ejemplo, Android nos proporciona una plantilla predefinida para mostrar los elementos de una lista. Esta plantilla la podremos utilizar con un adaptador de tipo ArrayAdapter:
setListAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, myarray));
En este ejemplo, simple_list_item_1 es una plantilla predefinida por la plataforma para mostrar los elementos asociados a una vista de tipo ListView. En la mayoría de las ocasiones con esta plantilla nos será suficiente.

Accediendo a los archivos originales de los recursos.

En raras ocasiones necesitaremos acceder directamente a los archivos originales de los recursos de una aplicación. Si los recursos se encuentran almacenados bajo la carpeta res/, solo podremos acceder a ellos a través de sus IDs de recurso. Para conseguir acceder a los archivos originales de nuestros recursos, tendremos que almacenarlos dentro de una carpeta especial llamada assets. El mecanismo encargado de la generación automática de IDs de recurso, no tendrá en cuenta esta carpeta. Por otro lado, la clase AssetManager nos facilitará el acceso a su contenido.

No obstante, si lo que necesitamos es un almacén de recursos en sus formatos originales (archivos de sonido y video, por ejemplo), es recomendable usar la carpeta res/raw y utilizar el método Resources.openRawResource() para acceder a su contenido.

No hay comentarios:

Publicar un comentario