Uso De Recursos En Android

¿Recién te has iniciado al mundo del Desarrollo Android y ya te topaste con la carpeta res?

¿Sabías que dentro de ella se ubican los recursos en Android?

Seguramente ya habrás utilizado sin darte cuenta los recursos que vienen por defecto al crear un nuevo proyecto en Android Studio.

Sin embargo es importante conocer la naturaleza, funcionamiento y ventajas que tiene usar por separado archivos para imágenes, strings, estilos, etc.

Sigue leyendo y aprenderás sobre los tipos de recursos que existen, la funcionalidad del archivo R.java, creación de recursos alternativos, acceso de recursos a través de XML y Java, obtención de valores y el uso de los recursos del sistema.

¿Qué Son Los Recursos En Android?

Los recursos son archivos o datos externos que soportan el comportamiento de nuestra aplicación Android. Con ello me refiero a imágenes, strings, colores, estilos, etc.

Formalmente en un proyecto, estos elementos se encuentran en la carpeta src/main/res. Allí encontrarás subdirectorios que agrupan los diferentes tipos de recursos.

Recursos En Android Studio

La idea del uso de recursos es dividir el código de tu app para mantener independencia. Todo con el fin de agregar variaciones de los archivos para adaptar la aplicación a diferentes tipos de pantallas, idiomas, versiones,  dimensiones, configuraciones de orientación, etc.

Por ejemplo…

No es lo mismo el espacio de un teléfono móvil a una tableta. Sin embargo se pueden crear variaciones de los recursos para que la aplicación se adapte a la densidad de pantalla de cada uno.

Tipos De Recursos

Los grupos de recursos se dividen en subdirectorios. Cada uno de ellos contiene archivos que cumplen una función específica dentro de la aplicación. Debes respetar esta estructura de documentos para no tener problemas en la ejecución.

La siguiente es una tabla de la mayoría de los tipos de recursos que podemos crear:

Nombre del subdirectorio Contenido
animator/ Alberga archivos XML con animaciones de propiedades para objetos.
anim/ Contiene archivos XML que representan animaciones especiales para views.
color/ Aquí encontrarás archivos XML con definiciones de listas de estados de color (Color State List). Estas listas determinan el color de un componente dependiendo del estado en que se encuentre.
drawable/ Recursos gráficos que puedan ser proyectados en pantalla. Generalmente encontrarás archivos de imagen como .png, .jpg o .gif, sin embargo es posible usar otros como: archivos nine-patch, listas de estado, drawables con múltiples niveles, drawables con figuras 2D definidas en XML, y muchas más.
mipmap/ Contiene el icono de la aplicación para evitar distorsión entre varias densidades de pantalla.
layout/ Archivos XML que contienen definiciones de la interfaz de usuario.
menu/ Archivos XML que establecen las características para los menús usados en la interfaz. Normalmente contienen definiciones sobre los ítems albergados en un menú y las agrupaciones entre ellos.
raw/ Almacena aquí todos aquellos archivos que deseas leer directamente como un flujo de caracteres estándar (InputStream).
values/ Archivos XML que contienen datos simples como enteros, strings, booleanos, colores. Puedes agrupar estos elementos en las siguientes convenciones de archivos:

  • strings.xml para cadenas
  • colors.xml para definiciones de colores en hexadecimal.
  • dimens.xml para dimensiones de márgenes, padding, tamaños, etc.
  • styles.xml para los estilos de interfaz que tendrá la aplicación.
  • arrays.xml para arreglos de elementos.
xml/ Contiene archivos XML con definiciones especiales requeridas en acciones con el framework de Android. O para usos que requieras en tus requerimientos, como parsear una estructura XML directamente en la aplicación.

Recursos Alternativos En Android

Un recurso alternativo es una variación de un recurso, que se ajusta a una característica de configuración en el dispositivo móvil donde se ejecuta la aplicación.

Esto se logra a través de una tabla de calificadores creada por Google que estandariza todas las configuraciones posibles que se puedan presentar.

Un calificador es un mecanismo gramatical que especifica el propósito de un recurso. Su sintaxis es la siguiente:

<nombre_recurso>-<calificador>

De seguro ya vas comprendiendo un poco porque al crear un nuevo proyecto en Android Studio vienen varias carpetas para el recurso mipmap.

Esto se debe a que cada variación contiene un calificador para especificarle a la aplicación que al momento de variar la densidad de pantalla, escoja el recurso que se ajuste a esta configuración.

Recursos Alternativos En Android

Por ejemplo mipmap-hdpi contendrá la variación del recurso ic_launcher.png para aquellos dispositivos con densidades de pantalla altas (~240dpi). Esta condición es especificada por el calificador hdpi.

Esto significa que la imagen debe estar especialmente creada para ajustarse a esta densidad. Así mismo, las demás imágenes deben ser creadas a la medida de su calificador.

Todas las variaciones responden a un mismo identificador, por eso tienen el mismo nombre de archivo "ic_launcher.png".

Precedencia de calificadores— Los calificadores tienen orden precedencia, es decir, para usar más de un calificador en un recurso es necesario ubicar primero los calificadores con mayor importancia. Si se desobedece esa secuencia, habrá calificadores que no tengan efecto.

La siguiente tabla muestra los calificadores existentes en orden de precedencia.

Calificador Valores/Sintaxis Ejemplo/Definición
Código Móvil del País mccxxx-mncxxx mcc732-mnc101 (Operador Claro en Colombia)
Idioma y región xx-rXX es-rCO (Español en Colombia)
Dirección del layout ldrtl, ldrtl ldrtl(lectura de derecha a izquierda), ldrtl(lectura de izquierda a derecha)
Ancho mínimo de la pantalla sw<N>dp sw480dp, sw240dp
Ancho disponible w<N>dp w600dp, w1024dp
Altura disponible h<N>dp h180dp
Tamaño de la pantalla small, normal, large, xlarge
  • small: dispositivos  QVGA con tamaños de 320x426dps.
  • normal: dispositivos HVGA con tamaños de 320x470dps.
  • large: dispositivos VGA con tamaños de 480x640dps.
  • xlarge: dispositivos HVGA con largo de 720×960 dps.
Aspecto de la pantalla long, notlong
  • long: pantallas amplias.
  • nolong: pantallas reducidas.
Orientación de la pantalla port, land
  • port: Orientación estilo portrait (vertical).
  • land: Orientación estilo landscape (horizontal).
Modo UI car, desk, television, appliance, watch
  • car: El dispositivo está conectado a un coche.
  • desk: El dispositivo está conectado a un PC.
  • television: El dispositivo está conectado a un TV.
  • appliance: El dispositivo está conectado a un elemento sin especificar.
  • watch: El dispositivo es un reloj.
Modo nocturno night, notnight
  • night: Modo nocturno activado.
  • notnight: Modo nocturno desactivado.
Densidad de pantalla ldpi
mdpi
hdpi
xhdpi
xxhdpi
xxxhdpi
nodpi
tvdpi
  • ldpi: Low-density, densidades de máximo 120dpi.
  • mdpi: Medium-density, máximo 160dpi.
  • hdpi: High-density, máximo 240dpi.
  • xhdpi: Extra-high-density, máximo 320dpi
  • xxhdpi: Extra-Extra-High-Density, máximo 480dpi.
  • xxxhdpi: Extra-extra-extra-high-density máximo 640dpi.
  • nodpi: aquí puedes situar objetos que no quieres redimensionar sea cual sea la densidad.
  • tvdpi: Densidades asociadas a smart tvs.
Tipo de pantalla táctil notouch
finger
  • notouch: Dispositivo sin pantalla táctil.
  • finger: Dispositivo con pantalla táctil.
Disponibilidad del teclado keysexposed
keyshidden
keyssoft
  • keysexposed: El dispositivo tiene un teclado disponible.
  • keyshidden: El dispositivo tiene un teclado físico, pero este está deshabilitado y tampoco existe un teclado táctil.
  • keyssoft: El dispositivo tiene un teclado táctil, ya sea que esté habilitado o no.
Método primario de entrada de texto nokeys
qwerty
12key
  • nokeys: El dispositivo no tiene un teclado físico.
  • qwerty: El dispositivo tiene un teclado físico del tipo “qwerty”.
  • 12key: El dispositivo tiene un teclado físico con teclas numéricas.
Disponibilidad de las teclas de navegación navexposed
navhidden
  • navexposed: El teclado de navegación está disponible.
  • navhidden: El teclado de navegación no está disponible.
Método primario de navegación no táctil. nonav
dpad
trackball
wheel
  • nonav: No una forma de navegación que no sea la pantalla táctil.
  • dpad: El dispositivo tiene un teclado direccional para navegar.
  • trackball: El dispositivo tiene una esfera de seguimiento para navegar.
  • wheel: El dispositivo tiene una rueda de navegación para navegar.
Versión de Android vN v17, v21

Para asociar múltiples calificadores a un recurso es necesario que los separes por guiones siguiendo el orden anterior.

Por ejemplo…

Declaremos la variación del subdirectorio values para la dirección de lectura izquierda-derecha y orientada al idioma inglés.

values-ldrtl-en/

Es sencillo, solo buscamos el orden de ambas características en la tabla. Primero va el sentido de lectura, así lo ubicamos separado por guion. Luego sigue el idioma, por lo que anteponemos un nuevo guion y añadimos el indicador en en segunda posición.

Crear Recursos En Android Studio

Para crear nuevos recursos en Android debes situarte en la carpeta res y luego añadir un nuevo subdirectorio o archivo de recurso, dependiendo del caso.

Por ejemplo, si deseas crear un subdirectorio para recursos tipo raw, entonces presionas click derecho en la carpeta res, selecciona New y luego eliges Android resource directory.

Crear Un Subdirectorio De Recursos En Android Studio

Esto abrirá un asistente que te permite seleccionar el tipo de recurso y aquellos calificadores que deseas incluirle.

New Resource Directory En Android Studio

Por ejemplo, si deseáramos añadir un calificador para los recursos raw orientados a idioma inglés, seleccionamos el calificador Locale. Este desplegará una lista para elegir el idioma y las ubicaciones. Prueba elegir idioma inglés y ubicación Estados Unidos.

Nuevo Recurso En Inglés Para Estados Unidos En Android Studio

Al confirmar, tendremos nuestro nuevo subdirectorio en la carpeta res.

Subdirectorio Con Calificadores En La Carpeta res

Para agregar un nuevo archivo de recurso es el mismo procedimiento. Presionas click derecho, dirígete a la opción New en el subdirectorio deseado y luego asignas un nombre u otros campos que se requieran, dependiendo del tipo de recurso.

Crear Nuevo Archivo De Recursos En Android Studio

Por ejemplo… al intentar crear un nuevo archivo dentro de res/values nos exigirán el nombre.

Nuevo Archivo De Recursos value

Acceder A Los Recursos En Android

Hasta ahora ya sabemos cómo agrupar los tipos de recursos y definir archivos XML para algunos de ellos.

Lo que sigue es comprender el acceso a sus valores desde el proyecto. Los recursos pueden ser accedidos en el código Java o en el código XML.

Para obtener la referencia de un recurso es necesario que se le asigne un identificador que lo diferencie y le indique al programador donde se encuentre.

Cada identificador se ubica en una clase llamada R a través de una constante enteraEsta clase es generada automáticamente por una herramienta del SDK llamada appt, por lo que no es recomendable editarlo manualmente.

Cada tipo de recurso existente dentro de la carpeta res es una clase anidada estática del archivo R.java.

Por ejemplo, el subdirectorio drawable puede ser accedido como R.drawable.

Ahora, si deseas obtener el identificador de un recurso, entonces usas el operador punto para acceder a los miembros de cada clase interna.

Por ejemplo, se tiene una imagen cuyo identificador es imagen_gato. Para acceder a su contenido solo navegas de la siguiente forma R.drawable.imagen_gato.

El archivo R.java en un proyecto tendría un aspecto similar al siguiente:

Archivo R.java En Android Studio

Acceder a los recursos desde Java— Ya vimos de forma general como podríamos obtener el ID de un recurso con la clase R. La sintaxis formal de acceso es la siguiente:

[<nombre_paquete>.]R.<tipo_recurso>.<nombre_recurso>

Donde,

  • [<nombre_paquete>.] es el nombre del paquete donde se encuentran alojados los recursos. No uses ninguno, si te estás refiriendo al paquete local.
  • <tipo_recurso> es una de las agrupaciones de recursos como por ejemplo xml.
  • <nombre_recurso> es el nombre del archivo asignado o el identificador de un elemento.

Existen muchas formas de implementar las referencias de los recursos dependiendo de la situación.

Por ejemplo…

1. Uno de los primeros usos que verás al crear un nuevo proyecto en Android Studio es la asignación de un layout a una actividad.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

En este caso se usa el método setContentView() para indicar el layout que dará forma visual a la actividad. El ejemplo muestra que será el recurso R.layout.activity_main, el cual representa al archivo activity_main.xml guardado en el subdirectorio layout.

2. Otro ejemplo lo vemos al momento de asignar un recurso de menú para crear la action bar de una actividad.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

En este caso se pasa el ID del archivo menu_main.xml alojado en el subdirectorio menu. Es por eso que usamos la referencia R.menu.menu_main.

3. También podemos usar recursos al momento de asignar el contenido a un ImageView (elemento que representa imágenes en la pantalla).

ImageView imagen = (ImageView) findViewById(R.id.imagen);
imagen.setImageResource(R.drawable.avatar);

Primero se obtiene el image view a través del método findViewById() y luego se le asigna el identificador del drawable R.drawable.avatar con el método setImageResource().

4. Tal vez uno de los más populares sea asignar un string a un TextView con el método setText(), el cuál recibe el identificador de un recurso tipo texto.

TextView titulo = (TextView) findViewById(R.id.titulo);
titulo.setText(R.string.texto_titulo);

Por el momento nos estamos refiriendo a la referencia de los recursos, pero…

¿Cómo obtener los valores directamente?

La respuesta está en la clase Resources.

Este elemento representa la ubicación de los recursos y su contenido. Podemos obtener una instancia dentro de una actividad con el método getResources().

A través de ella podemos acceder a los valores de cualquier tipo de recurso. Todo a través de sus métodos get*().

Si deseas obtener un recurso tipo string, entonces invocas a getString(), el cual recibe como parámetro el ID del recurso:

Resources resources = getResources();
String appName = resources.getString(R.string.app_name);

De forma similar, podemos obtener el valor entero de un recurso tipo color:

Resources resources = getResources();
int color = resources.getColor(R.color.colorAzul);

Para los arrays de strings también existe su correspondiente método:

Resources res = getResources();
String[] campeones_adc = res.getStringArray(R.array.campeones_adc);

Acceder a los recursos desde XML— Esta forma de referencia se da cuando dentro de un recurso definido en un archivo XML  necesitamos usar el valor de otro recurso.

Por ejemplo, cuando a un componente <TextView> dentro de un layout le asignamos el valor de un string definido en el archivo strings.xml.

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/titulo_texto" />

La forma en que se asigna el ID depende de la siguiente sintaxis:

@[<nombre_paquete>:]<tipo_recurso>/<nombre_recurso>

Donde,

  • @[<nombre_paquete>:] se refiere al paquete java donde está alojado el recurso (no pones nada si son los recursos locales).
  • <tipo_recurso> es el tipo de recurso representado como clase anidada en R.java. Por ejemplo string.
  • <nombre_recurso> es el nombre del archivo sin extensión o el valor del atributo android:name del componente.

Veamos algunos ejemplos:

1. Supón que dentro del recuro values/dimens.xml defines el padding de los textos de la siguiente forma.

dimens.xml

<resources>    
    <dimen name="padding_textos">16dp</dimen>    
</resources>

Ahora decides utilizarlo en el atributo android:padding de un texto. Para ello solo usas la sintaxis vista anteriormente refiriéndote a los recursos de tipo dimen.

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Texto"
    android:padding="@dimen/padding_textos"/>

Cada vez que intentes asignar un recurso en un atributo, Android Studio te ayudará con una búsqueda emergente para una selección más rápida.

Búsqueda Rápida De Recursos En Android Studio

2. Dentro del tema de la aplicación también es posible asignar valores de recursos. Supón que asignarás un azul índigo como color primario al tema. Para ello declaras el valor en tu recurso values/colors.xml.

<resources>
    <color name="colorPrimario">#3F51B5</color>
</resources>

Luego estableces el atributo colorPrimary con este recurso.

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimario</item>
    </style>
</resources>

Acceder a los recursos del sistema— Android contiene en su framework varias constantes de recursos que nos permitirán acceder a estilos, tamaños, colores, layouts, etc.

En ocasiones es de utilidad usarlos para evitar la declaración de elementos que ya existen. Para usarlos debemos referirnos al paquete android en cada acceso que realicemos.

Un buen ejemplo sería el uso de colores predeterminados.

<resources>
    
    <style name="AppTheme" parent="@android:style/Theme">
        <item name="android:windowBackground">@android:color/white</item>
    </style>

</resources>

El anterior estilo asigna el color blanco almacenado en el paquete del sistema al background de las actividades de la aplicación.

Otro ejemplo sería al momento de tomar las acciones del Up Button de una actividad dentro del método onOptionsItemSelected(). Este elemento está predeterminado por el sistema ya que nosotros no lo construimos, sin embargo podemos recibir sus eventos con el identificador android.R.id.home:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    switch (id) {
        case android.R.id.home:
            // Acciones
            return true;
    }

    return super.onOptionsItemSelected(item);
}

Ejemplos De Recursos

A continuación veremos de forma general como se crean algunos archivos de recurso en definición XML que pertenecen al subdirectorio values y son de uso frecuente.

Existen tipos de recursos que requieren explicaciones más detalladas como los estilos y los layouts, por lo que serán tratados individualmente en artículos separados.

Recursos de colores en Android— Todo archivo XML para recursos debe contener un nodo raíz del tipo <resources>.

Dentro de un archivo de colores (colors.xml) los elementos deben ser declarados con la etiqueta <color>. Debes asignar un nombre único con el atributo name y su contenido es un color en forma hexadecimal que empieza por el símbolo numeral '#'.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorAzul">#0057ff</color>
    <color name="colorRojo">#ff0044</color>
</resources>

El anterior código contiene dos recursos de color.

Android Studio te permite modificar el color a través de un asistente que se inicia al seleccionar el recuadro de color. Este se encuentra justo al lado izquierdo.

Recursos De Colores En Android Studio

El asistente te permitirá personalizar al máximo el color que deseas. Desde seleccionar manualmente la cantidad de azul, rojo, verde y alfa, hasta copiar el color de un pixel en tu escritorio.

Choose Color En Android Studio

Recursos strings en Android— Los recursos de tipo strings nos permiten almacenar valores que representan texto en nuestra aplicación.

Son de gran utilidad, ya que puedes crear variaciones de idioma para cada recurso string.

Como ya has visto, el archivo values/strings.xml ha sido designado por convención para contener este tipo de recursos.

Los elementos más comunes son strings simples con un solo contenido y arrays de strings que asocian varios elementos a un solo nombre.

Los strings simples se definen con la etiqueta <string>. Para darle un identificador usa el atributo name y asigna un nombre distintivo.

<string name="nombre_string">texto_string</string>

Los arrays se declaran con <string-array> y asignarles un nombre con el atributo name. Cada elemento irá en su interior declarado con un elemento <item> y su contenido será el texto que representa.

Veamos un ejemplo…

<resources>

    <!-- strings de contenido simple -->
    <string name="app_name">Mis Pruebas</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>

    <!-- Array de strings -->
    <string-array name="campeones_adc">
        <item>Caitlyn</item>
        <item>Draven</item>
        <item>Jinx</item>
        <item>Varus</item>
        <item>Tristana</item>
    </string-array>
</resources>

El anterior código muestra en la parte superior tres strings simples y en su parte inferior un array de strings con 5 ítems.

Una ventaja de usar Android Studio es que permite extraer textos hacia el archivo strings.xml a través de un asistente.

Si estuvieses definiendo un layout donde se encuentra el siguiente TextView:

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="Descripción de tareas"/>

Verás que el valor del atributo android:text aparecerá marcado.

Warning Lint En Android Studio

Este warning te está diciendo que sería buena idea extraer ese texto plano a un recurso string. Si presionas ALT+ENTER en esa posición, verás una lista de opciones. La que nos interesa es Extract string resource.

Extract string resource En Android Studio

Si seleccionas esta opción se desplegará un asistente que nos permitirá trasladar el texto plano al archivo strings.xml con su respectivo identificador.

Asistente Extract Resource En Android Studio

Una vez asignes el nombre, confirmas y ya tendrás tu nuevo recurso creado. Incluso el acceso por el text view será reemplazado.

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="@string/descripcion_tareas"/>

Recursos para dimensiones en Android— Los recursos de dimensión permiten almacenar valores de medidas basadas en las características de la pantalla del dispositivo.

Por convención, las dimensiones se incluyen dentro del archivo res/dimens.xml para diferenciar su naturaleza. Cada recursos de dimensión se especifica con la etiqueta <dimen>, a la cual debe añadírsele el atributo name para diferenciar su existencia. En su contenido se indica un número junto a la unidad de medida a implementar.

<dimen name="nombre_dimension">dimension</dimen>

Los siguientes son los tipos de medida que puedes usar:

  • dp: Medida basada en la densidad de pantalla, donde 1dp equivale a 1px. Esto significa que si la densidad varia, entonces las medidas en dp variarán dependiendo del factor. Esta unidad es muy útil para mantener el aspecto de los views en un layout.
  • sp: Es una medida similar a los dp, solo que su variación de proporciones se basa en el tamaño de la fuente del texto. Por lo que es buena opción usarla cuando definamos tamaños para los textos.
  • pt: Representa un factor de 1/72 puntos por pulgadas según el tamaño real de la pantalla.
  • px: Medida en pixeles de la pantalla. Debido a la gran variedad de tamaños de pantalla, no es recomendable adaptar los elementos basados en pixeles.
  • mm: Representa un milímetro basados en el tamaño real de la pantalla.
  • in: Medida en pulgadas basadas en el tamaño real de la pantalla.

El siguiente es un ejemplo donde se muestra una dimensión para el margen superior de un text view y su tamaño de fuente.

<resources>    
    <dimen name="margen_superior">16dp</dimen>
    <dimen name="fuente_texto">24sp</dimen>
</resources>

Conclusión

Este artículo te ha mostrado el uso de recursos en Android. Has aprendido como se agrupan según su naturaleza y de qué forma puedes crear variaciones alternativas.

Recuerda que es posible acceder a las referencias de los recursos tanto en otros recursos con formato XML así como en el código Java. También puedes obtener sus valores en el código a través de la clase Resources, la cual gestiona todo el manejo de recursos.

Cada tipo de recurso trae consigo una serie de características especiales que puedes explorar mas a fondo. Si lo deseas, puedes seguir con el uso de estilos en Android.