Tema 4
Tema 4
Tema 4
Introducción al tema
La Interfaz de usuario (UI) de su aplicación es todo con lo que el usuario puede ver e
interactuar. Android ofrece una variedad de componentes de interfaz de usuario pre-
construidos, tales como objetos de diseño estructurados conocidos como layouts y controles
de interfaz de usuario que le permiten construir la interfaz gráfica de usuario para su
aplicación. Android también ofrece otros módulos de interfaz de usuario para interfaces
especiales, como los cuadros de diálogo, las notificaciones y menús.
Todos los elementos de la interfaz de usuario de una aplicación para Android se construyen
utilizando objetos View y ViewGroup. Una View es un objeto que dibuja algo en la pantalla que
el usuario puede interactuar. Un ViewGroup es un objeto que contiene otros objetos View y
ViewGroup con el fin de definir el diseño de la interfaz.
Android ofrece una colección de ambas subclases View y ViewGroup que le ofrecen los
controles comunes de entrada (como botones y campos de texto) y diversos modelos de
diseño o layouts (como Linear Layout o Relative Layout, los dos más utilizados). En esta
ocasión vamos a concentrarnos en estos últimos, los Layouts, puesto que son aquellos con los
que generalmente iniciamos la estructura de nuestra interfaz de usuario.
La interfaz de usuario para cada componente de su aplicación se define utilizando una
jerarquía de objetos View y ViewGroup, como se muestra en la figura:
Cada ViewGroup es un contenedor invisible que organiza Views hijos, mientras que los View
Hijos pueden ser controles de entrada u otros widgets que dibujan una cierta parte de la
interfaz de usuario. Este árbol de jerarquía puede ser tan simple o complejo como usted
necesite que sea (pero la simplicidad es lo mejor siempre para el rendimiento).
4.1. Layouts
Un Layout es un objeto ViewGroup que define la estructura visual de una interfaz de usuario,
tales como la interfaz de usuario para una actividad o un app Widget. Por lo tanto cuando
hablamos de layout nos estamos refiriendo al diseño que deseamos aplicar a nuestras
interfaces de usuario. Puede definir un Layout de dos maneras:
Declarar elementos de interfaz de Usuario en XML. Android proporciona un
vocabulario XML sencillo que corresponde a las clases y subclases View, como las de
los widgets y layouts mismos.
Instanciar elementos layout en tiempo de ejecución. Su aplicación puede crear
objetos View y ViewGroup (y manipular sus propiedades) mediante programación.
El Framework Android le da la flexibilidad para utilizar uno o ambos de estos métodos para la
declaración y gestión de la interfaz de usuario de la aplicación. Por ejemplo, usted podría
declarar diseños predeterminados de su aplicación en XML, incluyendo los elementos de la
pantalla que aparecen en ellos y sus propiedades. A continuación, puede añadir código de la
aplicación que modifique el estado de los objetos de la pantalla, incluyendo los declarados en
XML, en tiempo de ejecución.
La ventaja de declarar su interfaz de usuario (UI) en XML, es que le permite separar mejor la
presentación de su aplicación del código que controla su comportamiento. Sus descripciones
de interfaz de usuario son externos a su código de la aplicación, lo que significa que usted
puede modificar o adaptar sin tener que modificar el código fuente y recompilar. Por ejemplo,
puede crear XML Layouts para diferentes orientaciones de pantalla, diferentes tamaños de
pantalla de dispositivos y diferentes idiomas. Además, declarando su layout en XML hace que
sea más fácil visualizar la estructura de su interfaz de usuario, por lo que es más fácil de
depurar algunos problemas. Como tal, esta semana nos centramos en la enseñanza de cómo
declarar su layout en XML.
En general, el vocabulario XML para declarar elementos de la UI sigue de cerca la estructura y
denominación de las clases y métodos, donde los nombres de los elementos corresponden a
los nombres de clases y los nombres de atributos corresponden a los métodos. De hecho, la
correspondencia es a menudo tan directa que se puede adivinar qué atributo XML
corresponde a un método de clase, o adivinar qué clase corresponde a un elemento XML en
cuestión. Sin embargo, tenga en cuenta que no todo el vocabulario es idéntico. En algunos
casos, hay diferencias de nomenclatura ligeras. Por ejemplo, el elemento EditText tiene un
atributo texto que corresponde EditText.setText().
Escribiendo el XML
Utilizando XML de Android, puede diseñar rápidamente Layouts de usuario y los elementos de
pantalla que contienen, de la misma manera como crea páginas web en HTML, con una serie
de elementos anidados.
Cada archivo de layout debe contener exactamente un elemento raíz, que debe ser un objeto
View o ViewGroup. Una vez que haya definido el elemento raíz, puede agregar objetos o
widgets de diseño adicionales como elementos secundarios para construir gradualmente una
jerarquía que define su diseño. Por ejemplo, aquí está un layout de XML que utiliza una
vertical LinearLayout que contiene un TextView y un botón:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MyActivity">
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
Atributos
Cada objeto View y ViewGroup soporta su propia variedad de atributos XML. Algunos
atributos son específicos de un objeto View (por ejemplo, TextView admite el atributo
textSize), pero estos atributos también son heredados por los objetos View que pueden
extender esta clase. Algunos son comunes a todos los objetos View, ya que se heredan de la
clase raíz View (como el atributo id). Y, otros atributos son considerados "parámetros de
diseño" (layouts parameters), los cuales son atributos que describen ciertas orientaciones de
diseño del objeto View, según la definición de objeto ViewGroup padre de ese objeto.
ID
Cualquier objeto View puede tener un ID asociado con él, para identificar unívocamente el
View dentro del árbol. Cuando se compila la aplicación, esta identificación se hace referencia
como un valor entero, pero la identificación se suele asignar en el archivo XML de diseño como
una cadena o String, en el atributo id. Este es un atributo XML común a todos los objetos View
(definidos por la clase View) y que se utiliza muy a menudo. La sintaxis de una identificación,
dentro de una etiqueta XML es:
android:id="@+id/my_button"
El símbolo (@) en el principio de la cadena, indica que el analizador sintáctico XML debe
analizar y ampliar el resto de la cadena de ID e identificar como un recurso ID. El plus-símbolo
(+) significa que este es un nuevo nombre de recurso que debe ser creado y añadido a
nuestros recursos (en el archivo R.java, el que es manejado de forma interna por Android y
nosotros como desarrolladores no podemos manipular). Veamos un ejemplo con un control:
Definimos un View en el archivo Layout y asignamos a este un único ID:
<Button android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/my_button_text"/>
A continuación, creamos una instancia del objeto View y lo obtenemos desde el diseño
mediante su ID, por lo general en el método onCreate() del archivo Java correspondiente a
nuestro Activity:
Un ID no tiene que ser único en todo el árbol, pero debe ser único dentro de la parte del árbol
que está buscando. Dado que a menudo se suele buscar en todo el árbol, es mejor que el ID
de cada View sea completamente único en lo posible.
Layout Parameters
Los atributos denominados layout_algo definen los parámetros layout para el View que son
apropiados de acuerdo al ViewGroup donde reside.
Cada clase ViewGroup implementa una clase anidada que extiende
de ViewGroup.LayoutParams. Esta subclase contiene los tipos de propiedades que definen el
tamaño y la posición de cada View hijo, según sea apropiado para el ViewGroup. Como se
puede ver en la figura, el ViewGroup padre define los parámetros de diseño para cada View
hijo (incluyendo el hijo ViewGroup).
Tenga en cuenta que cada subclase LayoutParams tiene su propia sintaxis para establecer
valores. Cada elemento hijo debe definir LayoutParams que sean apropiados para su padre,
aunque también puede definir diferentes LayoutParams para sus propios hijos.
Todos los ViewGroup incluyen una anchura y altura (layout_width y layout_height), y se
requiere de cada View que defina estos. Muchos LayoutParams también incluyen márgenes y
bordes opcionales.
Podemos especificar el ancho y la altura con las medidas exactas en unidades, aunque es
altamente probable que en la mayoría de las veces no sea necesario y tampoco
recomendable. Se utiliza una las siguientes constantes para establecer estos parámetros:
fill_parent: El elemento view puede crecer al tamaño de su padre que lo contiene. Está
obsoleto, a partir de API Level 8 remplazado por match_parent.
match_parent: El elemento view puede ser tan grande como su padre que lo contiene.
wrap_content: El elemento view puede crecer de acuerdo a su contenido, se ajusta al
contenido interno automáticamente.
wrap_content o match_parent, es un mejor enfoque, ya que ayuda a asegurar que su
aplicación se mostrará correctamente en una variedad de tamaños de pantalla del dispositivo.
Para más detalles acerca de los atributos disponibles para cada hijo de LinearLayout,
ver LinearLayout.LayoutParams.
android:layout_alignParentTop
Si es "true", hace que el borde superior de este View coincida con el borde superior del padre.
android:layout_centerVertical
Si es "true", centra este View verticalmente dentro de su padre.
android:layout_below
Positions the top edge of this view below the view specified with a resource ID.
Posiciona el borde superior de este View por debajo del View especificado con el recurso ID.
android:layout_toRightOf
Posiciona el borde izquierdo de este View a la derecha del View especificado con recurso ID.
Estos son sólo algunos ejemplos. Todos los atributos de diseño están documentados
en RelativeLayout.LayoutParams.
El valor para cada propiedad layout es o bien un valor booleano para habilitar una posición
respecto al padre RelativeLayout o un ID que hace referencia a otro VIew en el layout con el
que el View debe ser colocado.
En su layout XML, los Views se pueden declarar en cualquier orden. Por ejemplo, se puede
declarar que "view1" se coloca por debajo "view2" aunque "view2" es el último View
declarado en la jerarquía. El ejemplo siguiente muestra un escenario de este tipo:
Otro ejemplo, donde podemos observar de forma más clara que es indiferente el orden en que
se colocan los View puesto que lo que finalmente manda su posición son los atributos
RelativeLayout.LayoutParams:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
<TextView
android:id="@+id/view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
<TextView
android:id="@+id/view2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
<TextView
android:id="@+id/view3"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_above="@id/view2"
android:layout_below="@id/view1"
</RelativeLayout>
Se necesita disponer de un ListView con los nombres de los países de sudamérica. Cuando se
seleccione un país mostrar en un TextView la cantidad de habitantes del país seleccionado.
Creamos un nuevo Activity y utilizando nuestro diseñador gráfico agregamos un TextView
(llamado tv1) y un ListView (llamado listView1). Luego nuestro código Java del Activity debe
quedar de la siguiente manera:
public class MainActivity extends Activity {
private String[] paises = { "Argentina", "Chile", "Paraguay", "Bolivia",
"Peru", "Ecuador", "Brasil", "Colombia", "Venezuela", "Uruguay" };
private String[] habitantes = { "40000000", "17000000", "6500000",
"10000000", "30000000", "14000000", "183000000", "44000000",
"29000000", "3500000" };
private TextView tv1;
private ListView lv1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1=(TextView)findViewById(R.id.tv1);
lv1 =(ListView)findViewById(R.id.listView1);
ArrayAdapter <String> adapter = new
ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, paises);
lv1.setAdapter(adapter);
lv1.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int posicion, long id) {
tv1.setText("Población de "+ lv1.getItemAtPosition(posicion) + " es "+
habitantes[posicion]);
}
});
}
}
Definimos un objeto de tipo TextView y otro de tipo ListView donde almacenaremos las
referencias a los objetos que definimos en el archivo XML:
tv1=(TextView)findViewById(R.id.tv1);
lv1 =(ListView)findViewById(R.id.listView1);
Creamos un objeto de la clase ArrayAdapter de forma similar a como lo hicimos cuando vimos
la clase Spinner:
lv1.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int posicion, long id) {
tv1.setText("Población de "+ lv1.getItemAtPosition(posicion) + " es "+
habitantes[posicion]);
}
});
Dentro del método onItemClick modificamos el contenido del TextView con el nombre del país
y la cantidad de habitantes de dicho país. Este método recibe en el tercer parámetro la
posición del item seleccionado del ListView.
Cuando ejecutamos el proyecto podemos ver una interfaz en el emulador similar a esta:
Este GridView llenará toda la pantalla. Los atributos son bastante explicativos por sí mismos.
Para obtener más información acerca de los atributos válidos, consulte el GridView referencia.
4.- Abra el archivo HelloGridView.java e inserte el siguiente código en el método onCreate():
5.- Crear una nueva clase llamada ImageAdapter que extiende de BaseAdapter :
Al final del método getView(), la posición de número entero pasa en el método se utiliza para
seleccionar una imagen de la mThumbIds matriz, que se establece como el recurso de imagen
para el ImageView .
Todo lo que queda es definir el mThumbIds gama de recursos dibujables.
6.- Ahora ya puede ejecutar su aplicación.
4.2. Menús
Los menús son un componente de la interfaz de usuario común en muchos tipos de
aplicaciones. Para proporcionar una experiencia de usuario familiar y consistente, se debe
utilizar los APIs de Menú para presentar las acciones del usuario y otras opciones en sus
Activities.
Aunque la experiencia de diseño y de usuario para algunos elementos del menú han cambiado,
la semántica para definir un conjunto de acciones y opciones se sigue basando en los APIs de
menú. Debemos aprender a crear los tres tipos fundamentales de menús:
Para definir el menú, crear un archivo XML dentro de su proyecto en la carpeta /res/menu y
crear el menú con los siguientes elementos:
<Menú>
Define un menú, que es un contenedor para elementos de menú. Un elemento <menu> debe
ser el nodo raíz del archivo y puede contener uno o más elementos <item> y <grupo>.
<Elemento>
Crea un MenuItem, lo que representa un solo elemento en un menú. Este elemento puede
contener un elemento anidado <menu> con el fin de crear un submenú.
<Grupo>
Un contenedor opcional, invisible para elementos <item>. Este permite clasificar los
elementos de menú por los que comparten propiedades como el estado activo y visibilidad.
A continuación un ejemplo de menú denominado game_menu.xml:
El elemento <item> es compatible con varios atributos que puede utilizar para definir la
apariencia y el comportamiento de un elemento. Los elementos en el menú anterior incluyen
los siguientes atributos:
android: Identificación
Un identificador de recurso que es único para el tema, el cual permite que la aplicación puede
reconocer el elemento cuando el usuario selecciona.
android: icon
Una referencia a un drawable a utilizar como icono del elemento.
android: título
Una referencia a una cadena que se utilizará como título del ítem.
android: showAsAction
Especifica cuándo y cómo este item debe aparecer como un elemento de acción en la barra de
acción.
Estos son los atributos más importantes que debe usar, pero hay muchos más disponibles.
Para obtener información sobre todos los atributos admitidos, consulte el documento recurso
menú.
Puede agregar un submenú a un item en cualquier menú (excepto un submenú) añadiendo un
elemento <menu> como el hijo de un <item>. Los submenús son útiles cuando su aplicación
tiene un montón de funciones que se pueden organizar en temas, como los elementos de la
barra de menú de una aplicación para PC (Archivo, Editar, Ver, etc.). Por ejemplo:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/file"
android:title="@string/file" >
<!-- "file" submenu -->
<menu>
<item android:id="@+id/create_new"
android:title="@string/create_new" />
<item android:id="@+id/open"
android:title="@string/open" />
</menu>
</item>
</menu>
Para utilizar el menú en su Activity, debe inflar el recurso menú (convertir el recurso XML en un
objeto programable) usando MenuInflater.inflate().
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
También puede añadir elementos de menú utilizando add() y recuperar los elementos con
FindItem(). Puede revisar sus propiedades el MenuItem APIs.
El sistema llama a onCreateOptionsMenu() al iniciar la Activity, con el fin de mostrar los
elementos de la barra de acción.
Manejando los eventos Clic
Cuando el usuario selecciona un elemento del menú de opciones (incluyendo elementos de
acción en la barra de acciones), el sistema llama al método onOptionsItemSelected() de su
activity. Este método pasa el MenuItem seleccionado. Puede identificar el item llamando a
getItemID(), que devuelve el identificador único para el elemento del menú (definido por el
atributo android:id en el recurso menú o con un entero dado por el método add()). Ahora
podemos usar este ID para para realizar la acción apropiada. Por ejemplo:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.new_game:
newGame();
return true;
case R.id.help:
showHelp();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Como podemos notar en el código, cuando maneje con éxito un item del menú, debe devolver
true. Si no ha sido posible controlar el elemento del menú, debe llamar a la implementación
de la superclase onOptionsItemSelected() (esta implementación predeterminada devuelve
false).
Si su Activity incluye fragmentos, el sistema llama primero a onOptionsItemSelected() de la
actividad luego al de cada fragmento (en el orden que se añadió cada fragmento al Activity)
hasta que una devuelva verdadero o todos los fragmentos hallan sido llamados.
A partir de Android 3.0 se añadió la capacidad de definir el comportamiento de hacer clic en
una opción de menú en el mismo archivo XML, utilizando el atributo android:onClick. El valor
del atributo debe ser el nombre de un método definido en la Activity. El método debe ser
público y aceptar un único MenuItem parámetro cuando el sistema llama a este método. Para
obtener más información y un ejemplo, puede ver el recurso de menú.
Dado que hoy la recomendación es usar el modo de acción contextual, veamos cómo se realiza
este.
Para los Views que ofrecen acciones contextuales, por lo general, debe invocar el modo de
acción contextual sobre uno de los dos eventos (o ambos):
Si usted tiene una colección de artículos en un ListView o GridView y desea permitir a los
usuarios realizar acciones por lote, debe:
Por ejemplo:
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
@Override
}
@Override
deleteSelectedItems();
default:
}
}
@Override
}
@Override
// Here you can make any necessary updates to the activity when
// the CAB is removed. By default, selected items are deselected/unchecked.
}
@Override
// an invalidate() request
}
});
Eso es todo. Ahora, cuando el usuario selecciona un elemento con una clic largo, el sistema
llama al método onCreateActionMode() y muestra la barra de acción contextual con las
acciones especificadas. Mientras que la barra de acción contextual es visible, los usuarios
pueden seleccionar opciones adicionales.
En algunos casos en los que las acciones contextuales proporcionan puntos de acción
comunes, es posible que desee agregar una casilla de verificación o un elemento de interfaz de
usuario similar que permite a los usuarios seleccionar los elementos, porque no pueden
descubrir el comportamiento de un clic largo. Cuando un usuario selecciona la casilla de
verificación, puede invocar el modo de acción contextual estableciendo el respectivo elemento
de lista al estado comprobado con setItemChecked().
1.- Instancie un PopupMenu con su constructor, que toma la aplicación actual contexto y la
vista a la que se debe anclar el menú.
2.- Utilice MenuInflater para inflar su recurso de menú en el objeto menú devuelto por
PopupMenu.getMenu(). El nivel de la API de 14 o más, puede utilizar PopupMenu.inflate () en
su lugar.
Por ejemplo, aquí hay un botón con el atributo android:onClick que muestra un menú
desplegable:
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_overflow_holo_dark"
android:contentDescription="@string/descr_overflow_button"
popup.show();
El menú es ocultado cuando el usuario selecciona un elemento o toca fuera del área de menú.
Puede detectar este evento despedir u ocultar el menú utilizando
PopupMenu.OnDismissListener.
Manejando los eventos clic
Para realizar una acción cuando el usuario selecciona un elemento de menú, debe
implementar la interfaz PopupMenu.OnMenuItemClickListener y registrarlo en su PopupMenu
llamando a setOnMenuItemclickListener(). Cuando el usuario selecciona un elemento, el
sistema llama al onMenuItemClick() de la devolución de llamada de su interfaz. Por ejemplo,
de esta manera:
popup.setOnMenuItemClickListener(this);
popup.inflate(R.menu.actions);
popup.show();
@Override
archive(item);
delete(item);
return true;
default:
return false;
}