jueves, 31 de mayo de 2012

Recursos – Sintaxis de los Recursos


Para ir cerrando este camino de informacion sobre los recursos, vamos a ver que independientemente del tipo de recurso (de string y layout son los dos que hemos visto hasta ahora), Todos los recursos Android están identificados (o referenciados) por sus ids en código fuente Java.
La sintaxis que usamos para crear un ID de recurso en un fichero XML se llama resource-reference syntax (sintaxis de referencia a recurso). La sintaxis del atributo id que vimos anteriormente (@+id/text1) tiene la siguiente estructura formal:
@[package:]type/name
El tipo (type), corresponde a uno de los espacios de nombres de tipos de recursos disponible en R.java, que son algunos de los siguientes:
  • R.drawable
  • R.id
  • R.layout
  • R.string
  • R.attr
  • R.plural
  • R.array
En sintaxis de referencia a recursos XML, estos tipos se nombrarían así:
  • drawable
  • id
  • layout
  • string
  • attr
  • plurals
  • string-array
La parte name en @[package:]type/name corresponde al nombre dado al recurso (text1 en nuestro ejemplo anterior), este nombre, también será represantado como una constante entera en R.java.
Si no se especifica ningún paquete en @[package:] (de ahí que en la representación formal de la sintaxis aparezca entre corchetes, que quiere decir que es opcional); el par tipo/nombre será resuelto basándose en los recursos locales y en el archivo R.java local de nuestra aplicación.
Si especificamos android:type/name, el id referenciado será resuelto usando el paquete android y específicamente a través del archivo android.R.java. Podemos usar cualquier nombre de paquete java en el lugar de @[package:] para localizar el archivo R.java correcto y resolver la referencia al recurso en cuestión. Ahora que conocemos la sintaxis, vamos a analizar unos ejemplos. Nótese que la parte izquierda del ID android:id no es parte de la sintaxis. “android:id” simplemente indica que vamos a crear un id para un control como lo es el TextView.
<textview android:id=”text”> 
<!-- Error de compilación, como id no tomará cadenas de texto sin formato. -->
 
</textview><textview android:id=”@text”> 
<!--  Sintaxis incorrecta.  No disponde de tipo y nombre-->
<!--  debería ser @id/text, @+id/text o @string/string1-->
<!--  obtendremos el siguiente error: “No resource type specified”-->
 
</textview><textview android:id=”@id/text”>
<!--  Error: No hay ningún recurso que coincida con el id “text”-->
<!--  a no ser que lo hayamos definido nosotros mismos con anterioridad.-->
 
</textview><textview android:id=”@android:id/text”>
<!--  Error: el recurso no es público-->
<!--  lo que indica que no hay tal identificación en android.R.id-->
<!--  Por supuesto esto será válido si el archivo android R.java definió un id con este nombre.-->
 
</textview><textview android:id=”@+id/text”>
<!-- Correcto: crea un id llamado text  en el paquete R.java local.-->
</textview>
En la sintaxis “@+id/text”, el signo + tiene un significado especial. Le dice a Android que el ID puede no existir aún y, que en ese caso, cree uno nuevo y lo llame text.

Recursos compilados y no compilados


 

Recursos compilados y no compilados

Android soporta principalmente dos tipos de recursos: archivos XML y archivos raw (como imágenes, audio y vídeo). Incluso dentro de los archivos XML, has podido ver que en algunos casos los recursos están definidos como valores dentro del archivo XML (las cadenas de texto, por ejemplo). En otras ocasiones, un archivo XML es un recurso por sí mismo, como los Layout.
Podemos encontrar dos tipos de archivos XML: uno se compilará a un formato binario y el otro se copiará tal como es al dispositivo. Como ejemplo podemos poner los ficheros XML de recursos string y los ficheros de layout, ambos se compilarán a un formato binario antes de formar parte del paquete de instalación. Estos ficheros XML tienen formatos predefinidos en los que los nodos XML se traducen a IDs.
Por supuesto, también se pueden elegir archivos XML para guardarlos con su formato propio, estos archivos no serán interpretados y se les asignará un ID de recurso para poder identificarlos. Sin embargo, podemos querer que estos ficheros también se compilen a un formato binario. Para lograrlo, hay que colocarlos bajo el directorio ./res/xml. En tal caso, deberemos usar los lectores XMl que proporciona Android para acceder a los nodos del fichero.
Si colocamos cualquier tipo de archivo, incluyendo ficheros XML, bajo ./res/raw, no se compilarán a un formato binario. Deberemos entonces, para leerlos, usar Stream. Los archivos de audio y vídeo entran en esta categoría también.
Hay que destacar, que al formar parte el directorio rar de ./res/*, incluso estos archivos raw de audio y vídeo serán localizados como todos los demás recursos.
Como vimos, los recursos se almacenan en varios subdirectorios según su tipo, a continuación vemos algunos de los subdirectorios más importantes de la carpeta res.:
·         anim: Archivos compilados de animaciones.
·         drawable: Bitmaps
·         layout: definición de vistas y UI.
·         values: Arrays, colores, dimensiones, strings y estilos.
·         xml: fircheros XML arbitrarios.
·         raw: ficheros raw no compilados.
El compilador de recursos AAPT (Android Asset Packaging Tool), compila todos los recursos excepto los raw y lo coloca en el fichero .apk (Android package) final. Este fichero es el que contiene el código de las aplicaciones Android y los recursos, similar a los .jar de Java. Estos ficheros son los que usamos para instalar aplicaciones en Android.

miércoles, 30 de mayo de 2012

Programación Android: Recursos – Layout


En Android, cada pantalla de una aplicación habitualmente se carga desde un fichero XML que actua de recurso. Un recurso layout es un recurso clave que se usa en Android para componer la UI de nuestra aplicación. Vamos a considerar el segmenteo de código siguiente como ejemplo de una actividad en Android.
public class PrincipalActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}
La línea setContentView(R.layout.main); señala que hay una clase estática llamada R.layout y, que dentro de esa clase hay una constante entera llamada main que apunta a una vista definida por un fichero de recursos layout xML. El nombre del fichero XML es main.xml, el cual debe estar en el directorio./res/layout. El contenido de este fichero es el siguiente:
< ?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <textview android:id="@+id/text1"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="@string/hello" />
    <button android:id="@+id/b1"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="@string/hello"/>
 
</linearlayout>
Vamos a ver la composición de este fichero, como elemento raiz tenemos un elemento llamado , que contiene un TextView seguido de un Button. Un LinearLayout coloca a sus hijos uno detrás de otro vertical u horizontalmente.
Para cada pantalla que queramos hacer, necesitaremos ficheros layout distintos, mejor dicho, cada layout debe estar en un fichero, como ./res/layout/screen1.xml y ./res/layout/screen2.xml
Por cada archivo de layout que tengamos en ./res/layout, se generará una entrada en R.java. Por ejemplo, si tenemos estos dos archivos, file1.xml y file2.xml, en R.java aparecerá:
// ...
public static final class layout {
   public static final int file1=0x7f030000;
   public static final int file2=0x7f030001;
}
// ..
Las vistas definidas en estos layout, como el TextView son accesibles mediante código java a través sus IDs de recursos generadas en R.java.
TextView tv = (TextView) this.findViewById(R.id.text1);
tv.setText("Texto para el TextView")
En este ejemplo, hemos localizado el TextView usando el método findViewById() de la clase Activity. La constante R.id.text1 corresponde al ID definido para el TextView en el fichero XML, que creamos de la siguiente manera:
<textview android:id="@+id/text1"
....
/>
El valor del atributo id, indica que la constante llamada text1 será usada para identificar únicamente a esa vista. El signo + de +id/text1 significa que el ID text1 será creado si no existe. En la siguiente entrada se tratará la sintaxis de los recursos.

martes, 29 de mayo de 2012

Programación Android: Recursos – Usando recursos


A todos los recursos que colocamos en las subcarpetas de ./res/ se puede acceder a través de la clase R de nuestro proyecto.
Esta clase R la genera el comando aapt en una pasada anterior a la compilación
(Eclipse, por defecto, la va generando continuamente conforme cambiamos los
recursos). Contiene todos los identificadores de recursos para poder referenciarlos.
Al igual que la carpeta “res”, la clase R se organiza en subclases, así por ejemplo el icono que colocamos en ./res/drawable/icon tiene su correspondencia en
R.drawable.icon (que es un identificador estático de tipo int y sirve para acceder
al recurso).
Así entonces los ID de recurso están compuestos de:
Clase R que contienen todos los recursos.
Subclase de recurso, cada grupo tiene la suya (drawable, string, style, layout…).
Nombre del recurso que, según el tipo, será: el nombre del fichero sin la extensión o el atributo xml “android:name” si es un valor sencillo (cadena, estilo, etc.).
Tenemos dos formas de acceder a los recursos definidos en la clase R:
En el código, accediendo a las propiedades de la clase R directamente
(R.string.nombre).
En los ficheros XML, usando una notación especial: @grupo_recursos/
nombre_recurso, es decir, el recurso anterior se accedería con @string/nombre.
Si lo que queremos es acceder a un recurso definido por el sistema antepondremos el prefijo android:
  • Desde el código: android.R.layout.simple_list_item_1.
  • En los ficheros XML: @android:layout/simple_list_item_1.

 Empezaremos por un recurso muy común, los string:

Recursos string

Android permite definir strings en uno o más archivos XML de recursos. Estos archivos están bajo el directorio ./res/values. El nombre del archivo XML para este tipo de recurso puede ser cualquiera, pero por convención se suele llamar strings.xml. Veamos un ejemplo de este fichero:
< ?xml version="1.0" encoding="utf-8"?>
<resources>
   <string name="hello">Hello</string>
   <string name="app_name">Hello app_name</string>
</resources>
Cuando este archivo se crea o modifica, el plugin ADT de eclipse automáticamente creará o actualizará una clase java de nuestra aplicación llamada R.java alojada en el directorio ./gen, que contiene los IDs únicos para las dos cadenas que acabamos de crear.
Para el fichero strings.xml que acabamos de crear, tendremos lo siguiente en la clase R:
package nombre.de.nuestro.paquete;
 
public final class R {
   //.. otras entradas dependiendo de tu proyecto y aplicación
 
   public static final class string {
      //.. otras entradas dependiendo de tu proyecto y aplicación
      public static final int app_name=0x7f040001;
      public static final int hello=0x7f040000;
      //.. otras entradas dependiendo de tu proyecto y aplicación
   }
   //.. otras entradas dependiendo de tu proyecto y aplicación
}
Como vemos como primero R.java define una clase principal en el paquete raiz: public final class R. Depues, define una clase interna llamada public static final class string. R.java crea esta clase estática interna como espacio de nombres para guardar los IDs de los recursos string.
La definición de los dos public static final int llamados app_name y hello son los IDs de los recursos que representan nuestras cadenas de texto. Podemos usar estos IDs en cualquier lugar de nuestro código mediante R.string.hello o R.string.app_name
La estructura del fichero string.xml es muy fácil de seguir. Tenemos un elemento raiz llamado , seguido por uno o más elementos hijos . Cada elemento tiene una propiedad llamada name que será la que usará como identificador R.java.
Para comprobar que se permiten varios recursos de string en el directorio values, vamos a crear otro fichero llamado strings1.xml con lo siguiente:
< ?xml version="1.0" encoding="utf-8"?>
<resources>
   <string name="hello1">Hello</string>
   <string name="app_name1">Hello app_name</string>
</resources>
Ahora, el plugin ADT de eclipse se encargará de actualizar el fichero R.java, que contendrá lo siguiente:
package nombre.de.nuestro.paquete;
 
public final class R {
   //.. otras entradas dependiendo de tu proyecto y aplicación
 
   public static final class string {
      //.. otras entradas dependiendo de tu proyecto y aplicación
      public static final int app_name=0x7f040001;
      public static final int hello=0x7f040000;
      public static final int app_name1=0x7f040006;
      public static final int hello1=0x7f040005;
      //.. otras entradas dependiendo de tu proyecto y aplicación
   }
   //.. otras entradas dependiendo de tu proyecto y aplicación
}

Referenciando atributos de estilo

Cuando aplicamos estilos a nuestros layout puede interesarnos acceder a un
atributo concreto de un estilo, para eso tenemos una sintaxis específica que
podemos usar en nuestros XML:
?[:][/]
Así por ejemplo si queremos colocar un texto pequeño usaremos:
?android:attr.textAppearanceSmall
Si queremos, también podemos utilizar nuestros propios atributos.
Primero lo definimos con un tag “attr”·dentro de ./res/values/attr.xml.
< ?xml version="1.0" encoding="utf-8"?>
<resources>
     <attr name="cabecera" format="reference" />
</resources>
Ahora ya podemos usar esa propiedad en nuestros estilos:
Primero definimos un estilo de texto llamado “TituloRojo”, y luego lo aplicamos
al atributo que hemos creado llamado “Cabecera”. Obsérvese que como es un
atributo propio, no usamos el espacio de nombres “android:”.
Si luego quisiéramos acceder a este atributo al definir un layout podríamos usar
la sintaxis mencionada:
./res/layout/milayout
< ?xml version="1.0" encoding="utf-8"?>
<framelayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent">
<textview android:layout_width="fill_parent
     android:layout_height="fill_parent"
     android:text="No hay datos disponibles"
     style="?attr/cabecera" />
</framelayout>
./res/values/style.xml

< ?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MiTema" parent=
     "@android:style/Theme.Light">
     <item name="android:windowBackground">
     @drawable/fondo</item>
     <item name="cabecera">
     @style/TituloRojo</item>
</style>
<style name="TituloRojo"
     parent="@android:style/TextAppearance.Large">
     <item name="android:textColor">#FF0000</item>
     <item name="android:textStyle">bold</item>
</style>
</resources>