Tarea 4

Realizar mapa conceptual, en donde se difina claramente cada uno de los conceptos


Diseño

Un diseño define la estructura visual para una interfaz de usuario, como la IU para una actividad o widget de una app. Puedes declarar un diseño de dos maneras:

  • Declarar elementos de la IU en XML. Android proporciona un vocabulario XML simple que coincide con las clases y subclases de vistas, como las que se usan para widgets y diseños.
  • Crear una instancia de elementos del diseño en tiempo de ejecución. Tu aplicación puede crear objetos View y ViewGroup (y manipular sus propiedades) programáticamente.

El framework de Android te ofrece la flexibilidad de usar uno de estos métodos o ambos para declarar y administrar la IU de tu aplicación. Por ejemplo, podrías declarar los diseños predeterminados de la aplicación en XML, incluidos los elementos de pantalla que aparecerán en ellos y sus propiedades. Luego podrías agregar código en tu aplicación para modificar el estado de los objetos de la pantalla, incluidos los declarados en XML, en tiempo de ejecución.

La ventaja de declarar tu IU en XML es que te permite separar mejor la presentación de tu aplicación del código que controla su comportamiento. Tus descripciones de la IU son externas al código de tu aplicación, lo que significa que puedes modificarlo o adaptarlo sin tener que modificar el código fuente y volver a compilar. Por ejemplo, puedes crear diseños XML para diferentes orientaciones de pantalla, diferentes tamaños de pantalla de dispositivos y diferentes idiomas. Además, declarar el diseño en XML facilita la visualización de la estructura de tu IU, de modo que sea más fácil depurar problemas. Este documento se centra en enseñarte cómo declarar tu diseño en XML. Si te interesa crear instancias de objetos View en tiempo de ejecución, consulta las referencias de las clases ViewGroup y View.

En general, el vocabulario XML para declarar elementos de la IU sigue de cerca la estructura y la denominación de las clases y los métodos, en los que los nombres de los elementos coinciden con los nombres de las clases y los nombres de los atributos coinciden con los métodos. De hecho, la correspondencia generalmente es tan directa que puedes deducir qué atributo XML corresponde a un método de clase, o deducir qué clase corresponde a un elemento XML determinado. No obstante, ten en cuenta que no todo el vocabulario es idéntico. En algunos casos, hay pequeñas diferencias de denominación. Por ejemplo, el elemento EditText tiene un atributo text que coincide conEditText.setText().

Escribe en XML

Al usar vocabulario XML de Android, puedes crear rápidamente diseños de IU y de los elementos de pantalla que contienen, de la misma manera que creas páginas web en HTML, con una serie de elementos anidados.

Cada archivo de diseño debe contener exactamente un elemento raíz, que debe ser un objeto View o ViewGroup. Una vez que hayas definido el elemento raíz, puedes agregar widgets u objetos de diseño adicionales como elementos secundarios para crear gradualmente una jerarquía de vistas que defina tu diseño. Por ejemplo, aquí te mostramos un diseño XML que usa un LinearLayout vertical para incluir una TextView y un Button:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

<TextView android:id="@+id/text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Hello, I am a TextView" />

<Button android:id="@+id/button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Hello, I am a Button" />

</LinearLayout>

Después de declarar tu diseño en XML, guarda el archivo con la extensión .xml en el directorio res/layout/ de tu proyecto de Android para que pueda compilarse correctamente.

Puedes encontrar más información acerca de la sintaxis para un archivo de diseño XML en el documento Recursos de diseño.

Carga el recurso XML

Cuando compilas tu aplicación, cada archivo de diseño XML se compila en un recurso View. Debes cargar el recurso de diseño desde el código de tu aplicación, en tu implementación de callback Activity.onCreate(). Para hacerlo, llama a setContentView(), pásale la referencia a tu recurso de diseño en forma de: R.layout.layout_file_name. Por ejemplo, si tu diseño XML se guarda como main_layout.xml, lo cargarías para tu actividad de esta manera:

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main_layout);

}

El framework de Android llama al método callback onCreate() en tu actividad cuando se lanza la actividad (consulta el artículo acerca de ciclos de vida en el documento Actividades ).

Atributos

Todos los objetos View y ViewGroup admiten su propia variedad de atributos XML. Algunos atributos son específicos para un objeto View (por ejemplo, TextView admite el atributo textSize ), pero a esos atributos también los heredan otros objetos View que podrían extender esta clase. Algunos son comunes para todos los objetos View ya que se heredan desde la clase View raíz (como el atributo id). Otros atributos se consideran "parámetros de diseño" y son atributos que describen ciertas orientaciones de diseño del objeto View, tal como lo define el objeto principal ViewGroup de ese objeto.

ID

Cualquier objeto View puede tener un Id. con número entero asociado a él para identificar de forma exclusiva la vista en un árbol. Cuando se compila la aplicación, este ID se considera un número entero, pero el ID generalmente se asigna en el archivo XML del diseño como una string, en el atributo id. Este es un atributo XML común a todos los objetos View (definidos por la clase View) y lo usarás con mucha frecuencia. La sintaxis para un ID dentro de una etiqueta XML es la siguiente:

android:id="@+id/my_button"

El símbolo arroba (@) al comienzo de la string indica que el analizador de XML debe analizar y expandir el resto de la string de ID e identificarla como un recursos de ID. El símbolo más (+) significa que es un nuevo nombre de recurso que se debe crear y agregar a nuestros recursos (en el archivo R.java). El framework de Android ofrece otros recursos de ID. Al hacer referencia a un ID de recurso de Android, no necesitas el símbolo más, pero debes agregar el espacio de nombres de paquete android de la siguiente manera:

android:id="@android:id/empty"

Con el espacio de nombres de paquete android establecido, ahora hacemos referencia a un ID de la clase de recursos android.R, en lugar de la clase de recursos local.

Para crear vistas y hacer referencia a ellas desde la aplicación, puedes seguir este patrón común:

  1. Definir una vista/un widget en el archivo de diseño y asignarle un ID único:
    1. <Button android:id="@+id/my_button"
    2. android:layout_width="wrap_content"
    3. android:layout_height="wrap_content"
    4. android:text="@string/my_button_text"/>
  2. Luego, crear una instancia del objeto View y capturarlo desde el diseño (generalmente en el método onCreate()):
    1. Button myButton = (Button) findViewById(R.id.my_button);

Definir ID para objetos View es importante cuando se crea un RelativeLayout. En un diseño relativo, las vistas del mismo nivel pueden definir su diseño en función de otra vista del mismo nivel, que se identifica con un ID único.

No es necesario que un ID sea único en todo el árbol, pero debe ser único dentro de la parte del árbol en la que estás buscando (que a menudo puede ser el árbol completo, por lo que es mejor que, en lo posible, sea totalmente único).

Parámetros de diseño

Los atributos de diseño XML denominados layout_something definen parámetros de diseño para el objeto View que son adecuados para el objeto ViewGroup en el que reside.

Cada clase ViewGroup implementa una clase anidada que extiende ViewGroup.LayoutParams. Esta subclase contiene tipos de propiedad que definen el tamaño y la posición de cada vista secundaria, según resulte apropiado para el grupo de vistas. Como puedes ver en la figura 1, el grupo de vistas principal define parámetros de diseño para cada vista secundaria (incluido el grupo de vistas secundario).

Figura 1: Visualización de una jerarquía de vistas con parámetros de diseño asociados con cada vista.

Ten en cuenta que cada subclase LayoutParams tiene su propia sintaxis para configurar valores. Cada elemento secundario debe definir LayoutParams adecuados para su elemento primario, aunque también puede definir diferentes LayoutParams para sus propios elementos secundarios.

Todos los grupos de vistas incluyen un ancho y una altura (layout_width y layout_height), y cada vista debe definirlos. Muchos LayoutParams también incluyen márgenes y bordes opcionales.

Puedes especificar el ancho y la altura con medidas exactas, aunque probablemente no quieras hacerlo con mucha frecuencia. Generalmente usarás una de estas constantes para establecer el ancho o la altura:

  • wrap_content indica a tu vista que modifique su tamaño conforme a los requisitos de este contenido.
  • match_parent indica a tu vista que se agrande tanto como lo permita su grupo de vistas principal.

En general, no se recomienda especificar el ancho y la altura de un diseño con unidades absolutas como píxeles. En cambio, el uso de medidas relativas como unidades de píxeles independientes de la densidad (dp), wrap_content, o match_parent, es un mejor enfoque, ya que ayuda a garantizar que tu aplicación se muestre correctamente en dispositivos con pantallas de diferentes tamaños. Los tipos de medidas aceptados se definen en el documento Recursos disponibles.

Posición del diseño

La geometría de una vista es la de un rectángulo. Una vista tiene una ubicación, expresada como un par de coordenadas izquierda y superior, y dos dimensiones, expresadas como un ancho y una altura. La unidad para la ubicación y las dimensiones es el pixel.

Es posible recuperar la ubicación de una vista al invocar los métodos getLeft() y getTop(). El primero devuelve la coordenada izquierda, o X, del rectángulo que representa la vista. El segundo devuelve la coordenada superior, o Y, del rectángulo que representa la vista. Ambos métodos devuelven la ubicación de la vista respecto de su elemento primario. Por ejemplo, cuando getLeft() devuelve 20, significa que la vista se encuentra a 20 píxeles a la derecha del borde izquierdo de su elemento primario directo.

Además, se ofrecen varios métodos convenientes para evitar cálculos innecesarios, y se denominan getRight() y getBottom(). Estos métodos devuelven las coordenadas de los bordes derecho y superior del rectángulo que representa la vista. Por ejemplo, llamar a getRight() es similar al siguiente cálculo: getLeft() + getWidth().

Tamaño, relleno y márgenes

El tamaño de una vista se expresa con un ancho y una altura. En realidad, una vista tiene dos pares de valores de ancho y altura.

El primer par se conoce como ancho medido y altura medida. Estas dimensiones definen cuán grande quiere ser una vista dentro de su elemento primario. Las dimensiones medidas se pueden obtener llamando a getMeasuredWidth() y a getMeasuredHeight().

El segundo par se conoce simplemente como ancho y altura, o algunas veces ancho de dibujo y altura de dibujo. Estas dimensiones definen el tamaño real de la vista en la pantalla, al momento de dibujarlas y después del diseño. Estos valores pueden ser diferentes del ancho y la altura medidos, pero no necesariamente. El ancho y la altura se pueden obtener llamando a getWidth() y getHeight().

Para medir estas dimensiones, una vista considera su relleno. El relleno se expresa en píxeles para las partes izquierda, superior, derecha e inferior de la vista. El relleno se puede usar para desplazar el contenido de la vista una determinada cantidad de píxeles. Por ejemplo, un relleno izquierdo de 2 empuja el contenido de la vista 2 píxeles hacia la derecha del borde izquierdo. El relleno se puede ajustar usando el método setPadding(int, int, int, int) y se puede consultar llamando a getPaddingLeft(), getPaddingTop(), getPaddingRight() y getPaddingBottom().

Si bien una vista puede definir un relleno, no proporciona ningún tipo de soporte para márgenes. No obstante, los grupos de vistas sí lo proporcionan. Consulta ViewGroup y ViewGroup.MarginLayoutParams para obtener más información.

Para obtener más información acerca de las dimensiones, lee Valores de dimensión.

Diseños comunes

Cada subclase de la clase ViewGroup proporciona una manera única de mostrar las vistas que anidas en ella. Aquí te mostramos algunos de los tipos de diseño más comunes integrados en la plataforma Android.

Nota: Si bien puedes anidar uno o más diseños dentro de otro diseño para crear la presentación de tu IU, debes esforzarte por mantener tu jerarquía de diseño lo más sencilla posible. Tu diseño dibuja más rápido si tiene menos diseños anidados (una jerarquía de vistas ancha es mejor que una jerarquía de vista profunda).

Un diseño que organiza sus elementos secundarios en una sola fila horizontal o vertical. Si la longitud de la ventana supera la longitud de la pantalla, crea una barra de desplazamiento.

Te permite especificar la ubicación de los objetos secundarios en función de ellos mismos (el objeto secundario A a la izquierda del objeto secundario B) o en función del elemento primario (alineado con la parte superior del elemento primario).

Muestra páginas web.

Creación de diseños con un adaptador

Cuando el contenido de tu diseño sea dinámico o no sea predeterminado, puedes usar un diseño con la subclase AdapterView para completar el diseño con vistas durante el tiempo de ejecución. Una subclase de la clase AdapterView usa un Adapter para enlazar datos con su diseño. El Adapter se comporta como intermediario entre la fuente de datos y el diseño AdapterView; el Adapter recupera los datos (de una fuente como una matriz o una consulta a la base de datos) y convierte cada entrada en una vista que puedes agregar al diseño AdapterView.

Los diseños comunes respaldados por un adaptador incluyen:

Muestra una sola lista de columnas desplazable.

Muestra una cuadrícula desplazable de columnas y filas.

Relleno de una vista del adaptador con datos

Puedes completar una AdapterView, como ListView o GridView, enlazando la instancia AdapterView con un Adapter, que recupera datos de una fuente externa y crea una View que representa cada entrada de datos.

Android proporciona varias subclases deAdapter que resultan útiles para recuperar diferentes tipos de datos y generar vistas para una AdapterView. Los dos adaptadores más comunes son los siguientes:

Usa este adaptador cuando la fuente de datos sea una matriz. Según la configuración predeterminada, ArrayAdapter crea una vista para cada elemento de la matriz llamando a toString() en cada elemento y disponiendo los contenidos en una TextView.

Por ejemplo, si hay una matriz de strings que deseas visualizar en una ListView, inicializa un nuevo ArrayAdapter usando un constructor para especificar el diseño de cada string y la matriz de strings:

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,

android.R.layout.simple_list_item_1, myStringArray);

Los argumentos para este constructor son los siguientes:

  • El Context de tu app.
  • El diseño que contiene una TextView para cada string de la matriz.
  • La matriz de strings.

Luego, simplemente llama a setAdapter() en tu ListView:

ListView listView = (ListView) findViewById(R.id.listview);

listView.setAdapter(adapter);

Para personalizar el aspecto de cada elemento, puedes anular el método toString() de los objetos de tu matriz. Como alternativa, si deseas crear una vista para cada elemento que no sea una TextView (por ejemplo, si deseas una ImageView para cada elemento de la matriz), extiende la clase de ArrayAdapter y anula getView() a fin de mostrar el tipo de vista que desees para cada elemento.

Usa este adaptador cuando tus datos provengan de un Cursor. Cuando uses SimpleCursorAdapter, debes especificar un diseño para cada fila en el Cursor y qué columnas del Cursor se deben insertar en qué vistas del diseño. Por ejemplo, si deseas crear una lista de nombres y números de teléfono de personas, puedes realizar una consulta que muestre un Cursor con una fila para cada persona y columnas para los nombres y los números. Luego, crearás una matriz de strings que especifique las columnas del Cursor desees en el diseño para cada resultado y una matriz con valores enteros que especifique las vistas correspondientes en las que se deba colocar cada columna:

String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,

ContactsContract.CommonDataKinds.Phone.NUMBER};

int[] toViews = {R.id.display_name, R.id.phone_number};

Cuando creas una instancia del SimpleCursorAdapter, pasa el diseño que se debe usar para cada resultado, el Cursor que contiene los resultados y estas dos matrices:

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,

R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);

ListView listView = getListView();

listView.setAdapter(adapter);

Luego, el SimpleCursorAdapter crea una vista para cada fila en el Cursor usando el diseño proporcionado al insertar cada elemento fromColumnsen la vista toViews correspondiente.

.

Si durante el ciclo de vida de tu aplicación cambias los datos subyacentes que lee tu adaptador, debes llamar a notifyDataSetChanged(). Esto le notificará a la vista anexada que se modificaron los datos y que debe actualizarse.

Manejo de eventos de clic

Puedes responder a eventos de clic en cada elemento de una AdapterView al implementar la interfaz AdapterView.OnItemClickListener. Por ejemplo:

// Create a message handling object as an anonymous class.

private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {

public void onItemClick(AdapterView parent, View v, int position, long id) {

// Do something in response to the click

}

};

listView.setOnItemClickListener(mMessageClickedHandler);