Carta
Carta
Carta
El SDK de Android nos proporciona tres tipos de botones: los clásicos de texto (Button), los
que pueden contener una imagen (ImageButton), y los de tipo on/off
(ToggleButton y Switch).
1 <Button android:id="@+id/BtnBotonSimple"
android:text="@string/click"
2
android:layout_width="wrap_content"
3 android:layout_height="wrap_content" />
4
1 <ToggleButton android:id="@+id/BtnToggle"
android:textOn="@string/on"
2
android:textOff="@string/off"
3 android:layout_width="wrap_content"
4 android:layout_height="wrap_content" />
5
Un control Switch es muy similar al ToggleButton anterior, donde tan sólo cambia su
aspecto visual, que en vez de mostrar un estado u otro sobre el mismo espacio, se muestra
en forma de deslizador o interruptor. Su uso sería completamente análogo al ya comentado:
1 <Switch android:id="@+id/BtnSwitch"
android:textOn="@string/on"
2
android:textOff="@string/off"
3 android:layout_width="wrap_content"
4 android:layout_height="wrap_content" />
5
1 <ImageButton android:id="@+id/BtnImagen"
android:layout_width="wrap_content"
2
android:layout_height="wrap_content"
3 android:contentDescription="@string/icono_ok"
4 android:src="@drawable/ic_estrella" />
5
Esto nos da acceso a Asset Studio, donde podremos indicar el tipo de imagen a añadir (icono
de lanzador, icono de action bar, icono de notificación, …), el origen de la imagen
(Image = Fichero externo, Clipart = Colección de iconos estandar, Text = Texto
personalizado), el tema de nuestra aplicación (lo que afectará al color de fondo y primer
plano de los iconos seleccionados), y el nombre del recurso a incluir en el proyecto.
Así, en nuestro caso de ejemplo, seleccioné «Clipart» como origen de la imagen, seleccioné
el icono de estrella mediante el botón «Choose», e indiqué el nombre «ic_estrella»:
Al pulsar el botón Next el sistema consulta en qué módulo del proyecto y en qué carpeta de
recursos del módulo colocará los recursos creados para el icono. Además, como podemos
ver en la siguiente imagen Asset Studio se encarga de crear el icono para las distintas
densidades de pixeles y colocarlo en su carpeta de recursos correspondiente.
Cabe decir además, que aunque existe este tipo específico de botón para imágenes,
también es posible añadir una imagen a un botón normal de tipo Button, a modo de
elemento suplementario al texto (compound drawable). Por ejemplo, si quisiéramos añadir
un icono a la izquierda del texto de un botón utilizaríamos la
propiedad android:drawableLeft indicando como valor el descriptor (ID) de la imagen que
queremos mostrar, y si fuera necesario podríamos indicar también el espacio entre la
imagen y el texto mediante la propiedad android:drawablePadding:
1 <Button android:id="@+id/BtnBotonMasImagen"
android:text="@string/click"
2 android:drawableLeft="@drawable/ic_estrella"
3 android:drawablePadding="5dp"
4 android:layout_width="wrap_content"
5 android:layout_height="wrap_content" />
6
1 btnBotonSimple = (Button)findViewById(R.id.BtnBotonSimple);
2
btnBotonSimple.setOnClickListener(new View.OnClickListener() {
3
public void onClick(View arg0)
4 {
5 lblMensaje.setText("Botón Simple pulsado!");
6 }
7 });
8
En el caso de un botón de tipo ToggleButton o Switch suele ser de utilidad conocer en qué
estado ha quedado el botón tras ser pulsado, para lo que podemos utilizar su
método isChecked(). En el siguiente ejemplo se comprueba el estado del botón tras ser
pulsado y se realizan acciones distintas según el resultado.
1 btnToggle = (ToggleButton)findViewById(R.id.BtnToggle);
2
btnToggle.setOnClickListener(new View.OnClickListener() {
3
public void onClick(View arg0)
4 {
5 if(btnToggle.isChecked())
6 lblMensaje.setText("Botón Toggle: ON");
7 else
lblMensaje.setText("Botón Toggle: OFF");
8 }
9 });
10
11
1 <selector
xmlns:android="http://schemas.android.com/apk/res/android">
2 <item android:state_checked="false"
3 android:drawable="@drawable/toggle_off" />
4 <item android:state_checked="true"
android:drawable="@drawable/toggle_on" />
</selector>
En el código anterior vemos cómo se asigna a cada posible estado del botón una imagen
(un elemento drawable) determinada. Así, por ejemplo, para el estado “pulsado”
(state_checked=”true”) se asigna la imagen toggle_on.
1 <ToggleButton android:id="@+id/BtnPersonalizado"
android:textOn="@string/on"
2
android:textOff="@string/off"
3 android:layout_width="wrap_content"
4 android:layout_height="wrap_content"
5 android:background="@drawable/toggle_style" />
6
1 <ImageButton android:id="@+id/BtnSinBorde"
android:layout_width="wrap_content"
2
android:layout_height="wrap_content"
3 android:contentDescription="@string/icono_ok"
4 android:src="@drawable/ic_estrella"
5 style="?android:borderlessButtonStyle"/>
6
En la siguiente imagen vemos cómo quedaría este botón integrado dentro de
un LinearLayout y alineado a la derecha:
El separador vertical que se muestra entre el texto y el botón se consigue utilizando las
propiedades showDividers, divider, y dividerPadding del layout contenedor
(para mayor claridad puede consultarse el código completo):
1 <LinearLayout
android:id="@+id/BarraBtnSinBorde"
2
android:layout_width="match_parent"
3 android:layout_height="wrap_content"
4 android:orientation="horizontal"
5 android:showDividers="middle"
6 android:divider="?android:dividerVertical"
android:dividerPadding="6dp" >
7
8
Otro lugar muy habitual donde encontrar botones sin borde es en las llamadas barras de
botones (button bar) que muestran muchas aplicaciones. Para definir una barra de botones,
utilizaremos normalmente como contenedor un LinearLayout horizontal e
incluiremos dentro de éste los botones (Button) necesarios, asignando a cada
elelemento su estilo correspondiente, en este caso buttonBarStyle para el
contenedor, y buttonBarButtonStyle para los botones. En nuetro ejemplo
crearemos una barra con dos botones, Aceptar y Cancelar, que quedaría así:
1 <LinearLayout
android:id="@+id/BarraBotones"
2
android:layout_width="match_parent"
3 android:layout_height="wrap_content"
4 android:orientation="horizontal"
5 android:layout_alignParentBottom="true"
6 style="?android:attr/buttonBarStyle">
7
<Button android:id="@+id/BtnAceptar"
8 android:layout_width="wrap_content"
9 android:layout_height="wrap_content"
10 android:layout_weight="1"
11 android:text="@string/Aceptar"
12 style="?android:attr/buttonBarButtonStyle" />
13
<Button android:id="@+id/BtnCancelar"
14 android:layout_width="wrap_content"
15 android:layout_height="wrap_content"
16 android:layout_weight="1"
17 android:text="@string/Cancelar"
style="?android:attr/buttonBarButtonStyle" />
18
19 </LinearLayout>
20
21
22
23
Con la reciente publicación por parte de Google de la librería Design Support Library, añadir
este tipo de botones a nuestras aplicaciones es algo de lo más sencillo, y además
aseguramos su compatibilidad no sólo con Android 5.x sino también con versiones
anteriores. En esta librería se incluye un nuevo componente
llamado FloatingActionButton con la funcionalidad y aspecto deseados.
Lo primero que tendremos que hacer para utilizarlo será añadir la librería indicada a nuestro
proyecto.
Una vez añadida la referencia a la librería, salvamos el fichero y nos aseguramos de pulsar
la opción «Sync Now» que nos aparecerá en la parte superior derecha del editor de
código:
Una vez añadida la librería al proyecto como se describe en la nota anterior, podremos
añadir un botón flotante a nuestra interfaz añadiendo un nuevo elemento a nuestro layout
principal activity_main.xml de la siguiente forma:
1 <android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
2
android:layout_width="wrap_content"
3 android:layout_height="wrap_content"
4 android:src="@drawable/ic_add"
5 app:fabSize="normal"
6 app:borderWidth="0dp" />
7
¿Y como seleccionamos el color del botón? Pues bien, si no indicamos nada, el botón
flotante tomará por defecto el accent color si lo hemos definido en el tema de la
aplicación (más información en el artículo sobre la Action Bar) o el color de selección actual.
Si queremos utilizar otro color debemos hacerlo desde el código java de la aplicación, por
ejemplo en el onCreate() de la actividad principal, llamando al
método setBackgroundTintList() del control FloatingActionButton.
1 fabButton = (FloatingActionButton)findViewById(R.id.fab);
2
fabButton.setBackgroundTintList(
3
getResources().getColorStateList(R.color.fab_color));
4
Como parámetro debemos pasarle un objeto de tipo ColorStateList, que no es más que un
selector de color (similar al selector que creamos antes para el ToggleButon personalizado)
que crearemos en la carpeta /res/color por ejemplo con el nombre fab_color.xml y que
recuperaremos en nuestro código mediante el método getResources().
getColorStateList().
1 <selector
xmlns:android="http://schemas.android.com/apk/res/android">
2
<item android:state_pressed="true" android:color="#B90000" />
3 <item android:color="#FF0000"/>
4 </selector>
Como podemos ver, en el selector hemos definido el color normal del botón y su color
cuando está pulsado.
Para terminar, en la imagen siguiente se muestra la aplicación de ejemplo completa, donde
se puede comprobar el aspecto de cada uno de los tipos de botón comentados:
Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este
artículo accediendo a la pagina del curso en GitHub.
Controles RadioGroup y RadioButton
Nuestro problema solo requiere dos controles de tipo RadioButton. Para borrarlo lo
podemos hacer directamente del formulario seleccionándolo y presionando la tecla delete
o seleccionándolo desde la ventana "Outline" y luego presionando la tecla delete.
Ahora a los dos controles de tipo RadioButton definimos sus id (los llamaremos r1 y r2
respectivamente) Cambiamos sus propiedades text por los textos "sumar" y "restar".
No olvidemos también cambiar los id de los controles EditText por et1 y et2 (igual que en el
problema anterior) por último agreguemos un botón y un TextView para mostrar el
resultado Inicializamos las propiedades del botón con los valores:
id : button1
text : operar
id : tv3
text : resultado
Podemos controlar en la ventana "Outline" el id definido para cada control (tv1, et1, tv2,
et2, radioGroup1, r1, r2, button1, tv3) También podemos observar de que clase es cada
control visual y el texto de la propiedad text para aquellos controles que tienen sentido su
inicialización.
Si nuestro problema requería más de 3 RadioButton deberíamos arrastrar dentro del
RadioGroup otros controles de tipo RadioButton que se encuentran también en la pestaña
de "Form Widgets"
Captura del evento clic del button e identifiación del RadioButton seleccionado.
package com.javaya.proyecto003;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et1=(EditText)findViewById(R.id.et1);
et2=(EditText)findViewById(R.id.et2);
tv3=(TextView)findViewById(R.id.tv3);
r1=(RadioButton)findViewById(R.id.r1);
r2=(RadioButton)findViewById(R.id.r2);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to
the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main,
menu);
return true;
}
Primero debemos enlazar el objeto button1 con el método operar. Para esto similar al
problema anterior seleccionamos el control button1 y cambiamos la propiedad OnClick por
el valor operar (si no hacemos esto nunca se ejecutará el método operar de la clase
MainActivity) Como podemos ver el código fuente es igual al problema anterior. Tenemos
dos objetos más que debemos inicializar en el método onCreate:
r1=(RadioButton)findViewById(R.id.r1);
r2=(RadioButton)findViewById(R.id.r2);
Las variables r1 y r2 son de la clase RadioButton y son necesarios en el método operar para
verificar cual de los dos RadioButton están seleccionados. La clase RadioButton tiene un
método llamado isChecked que retorna true si dicho elemento está seleccionado:
No olvidemos inicializar la propiedad OnClick del objeto button1 con el valor "operar" (es el
nombre del método a ejecutarse cuando se presione el botón y lo implementa la clase que
hacemos)
Código fuente:
package com.androiya.proyecto004;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et1=(EditText)findViewById(R.id.et1);
et2=(EditText)findViewById(R.id.et2);
tv3=(TextView)findViewById(R.id.tv3);
checkBox1=(CheckBox)findViewById(R.id.checkBox1);
checkBox2=(CheckBox)findViewById(R.id.checkBox2);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to
the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main,
menu);
return true;
}
En el método onCreate los inicializamos con los objetos definidos en el archivo XML:
checkBox1=(CheckBox)findViewById(R.id.checkBox1);
checkBox2=(CheckBox)findViewById(R.id.checkBox2);
En el método operar debemos definir dos if a la misma altura ya que los dos controles de
tipo CheckBox pueden estar seleccionados simultaneamente. Definimos una variable de
tipo String y la inicializamos con cadena vacía para el caso en que los dos CheckBox no estén
seleccionados:
String resu="";
if (checkBox1.isChecked()==true) {
int suma=nro1+nro2;
resu="La suma es: "+ suma;
}
if (checkBox2.isChecked()==true) {
int resta=nro1-nro2;
resu=resu + " La resta es: "+ resta;
}
tv3.setText(resu);
Control Spinner
El objetivo de este concepto es practicar lo visto hasta ahora e incorporar el control visual
Spinner.
El control Spinner muestra una lista de String y nos permite seleccionar uno de ellos. Cuando
se lo selecciona se abre y muestra todos sus elementos para permitir seleccionar uno de
ellos.
Lo nuevo en este problema es la inserción de un control de tipo Spinner que se encuentra
en la pestaña "Form Widgets":
Definimos la propiedad id con el valor spinner1 (valor por defecto).
En la siguiente imagen en la ventana "Outline" de Eclipse podemos observar los objetos
dispuestos en el formulario, sus Id, sus textos y de que clase son cada uno:
No olvidemos inicializar la propiedad OnClick del objeto button1 con el valor "operar"
(dicho nombre es el método que debemos implementar)
Código fuente:
package com.javaya.proyecto005;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et1=(EditText)findViewById(R.id.et1);
et2=(EditText)findViewById(R.id.et2);
tv3=(TextView)findViewById(R.id.tv3);
spinner1 = (Spinner)
findViewById(R.id.spinner1);
String
[]opciones={"sumar","restar","multiplicar","dividi
r"};
ArrayAdapter<String> adapter = new
ArrayAdapter<String>(this,android.R.layout.simple_
spinner_item, opciones);
spinner1.setAdapter(adapter); }
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to
the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main,
menu);
return true;
}
}
else
if (selec.equals("dividir")) {
int divi=nro1/nro2;
String
resu=String.valueOf(divi);
tv3.setText(resu);
}
}
Luego mediante una serie de if anidados verificamos si debemos sumar, restar, multiplicar
o dividir:
if (selec.equals("sumar")) {
int suma=nro1+nro2;
String resu=String.valueOf(suma);
tv3.setText(resu);
} else
if (selec.equals("restar")) {
int resta=nro1-nro2;
String resu=String.valueOf(resta);
tv3.setText(resu);
}
else
if (selec.equals("multiplicar")) {
int multi=nro1*nro2;
String resu=String.valueOf(multi);
tv3.setText(resu);
}
else
if (selec.equals("dividir")) {
int divi=nro1/nro2;
String resu=String.valueOf(divi);
tv3.setText(resu);
}
Control ListView
El control ListView a diferencia del Spinner que se cierra luego de seleccionar un elemento
permanecen visibles varios elementos (se lo utiliza cuando hay que mostrar muchos
elementos)
Si la lista no entra en el espacio que hemos fijado para el ListView nos permite hacer scroll
de los mismos.
El control ListView se encuentra en la pestaña "Compositive".
Problema:
Disponer un ListView con los nombres de paises de sudamérica. Cuando se seleccione un
país mostrar en un TextView la cantidad de habitantes del país seleccionado.
La interfaz visual a implementar es la siguiente (primero disponemos un TextView (llamado
tv1) y un ListView (llamado listView1)):
Código fuente:
package com.javaya.proyecto006;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import
android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
@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]);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to
the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_mai
n, menu);
return true;
}
Primero definimos dos vectores paralelos donde almacenamos en uno los nombres de
paises y en el otro almacenamos la cantidad de habitantes de dichos paises:
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"};
Definimos un objeto de tipo TextView y otro de tipo ListView donde almacenaremos las
referencias a los objetos que definimos en el archivo XML:
private TextView tv1;
private ListView lv1;
En el método onCreate obtenemos la referencia a los dos objetos:
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:
ArrayAdapter<String> adapter = new
ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, paises);
lv1.setAdapter(adapter);
Llamamos al método setOnItemClicListener de la clase ListView y le pasamos como
parámetro una clase anónima que implementa la interfaz OnItemClickListener (dicha
interfaz define el método onItemClick que se dispara cuando seleccionamos un elemento
del ListView):
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:
Crear Layouts En Android Studio
Dentro de la estructura de un proyecto en Android Studio existe el directorio res para el
almacenamiento de recursos de la aplicación que se está desarrollando.
Las definiciones XML para los layouts se guardan dentro del subdirectorio layout.
Para crear un layout nuevo, solo presiona click derecho y ve a New > Layout resource file.
Normalmente cuando creas un nuevo proyecto en Android Studio con una actividad en
blanco, se genera automáticamente un layout. Algo como:
<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=".ActividadPrincipal">
<TextView android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
En este caso, tenemos un elemento raíz llamado RelativeLayout, el cual contiene un texto
con ciertas alineaciones establecidas.
Cada recurso del tipo layout debe ser un archivo XML, donde el elemento raíz solo puede
ser un ViewGroup o un View. Dentro de este elemento puedes incluir hijos que definan la
estructura del diseño.
Algunos de los view groups más populares son:
LinearLayout
FrameLayout
RelativeLayout
TableLayout
GridLayout
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.actividad_principal);
}
Es necesario pasar la referencia del layout que existe dentro del archivo R.java. En el código
anterior, cargamos un layout llamado actividad_principal.xml.
Atributos De Un Layout
Todas las características de un ViewGroup o un View son representadas a través
de atributos que determinan algún aspecto.
Encontrarás atributos para el tamaño, la alineación, padding, bordes, backgrounds, etc.
Cada atributo XML descrito para un componente tiene una referencia en la clase Java que
lo representa. Esto quiere decir que al usar un elemento <TextView>, nos estamos
refiriendo a la clase TextView.
Identificador de un view— Existe un atributo que heredan todos los elementos llamado id.
Este representa un identificador único para cada elemento. Lo que permite obtener una
referencia de cada objeto de forma específica. La sintaxis para el id sería la siguiente:
android:id="@+id/nombre_identificador"
Donde el símbolo '@' indica al parser interno de XML, que comienza un nuevo identificador
para traducir. Y el símbolo '+' declara que dicho id no existe aún. Por ello se da la orden para
crear el identificador dentro del archivo R.java a partir del string que proporcionamos.
Obtener view en una actividad con findViewById()— Una vez definido un id para los views
que deseas manipular en el código, se usa el método findViewById() para obtener sus
instancias.
Un ejemplo sería obtener la referencia del TextView que Android Studio incluye dentro de
una nueva actividad en blanco. Supongamos que le asignamos un id referenciado con el
nombre “texto_hello_world”.
<TextView
android:id="@+id/texto_hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
La estrategia es sencilla. Simplemente declaras un objeto del tipo que de view que buscas y
luego asignas el resultado que produce findViewById(). Este recibe como parámetro la
referencia que se creó dentro de R.java, la cual tiene el mismo nombre del string que
usamos.
Importante realizar el casting del view con el tipo deseado, que en el caso anterior
era TextView.
Cuando estés digitando y pongas el punto en R.id. , verás cómo Android Studio despliega
automáticamente todos los identificadores que existen hasta el momento.
Esta lista de acceso rápido filtrará los identificadores cuando escribas una palabra
semejante.
El gran número de identificadores extraños que aparecen, hacen parte de recursos
previamente definidos en nuestro proyecto que mantienen la compatibilidad de nuestra UI.
Por otro lado, también puedes referirte a identificadores propios del sistema, con la
clase android.R. A medida que vayas leyendo mis siguientes tutoriales de Desarrollo
Android, podrás ver algunos usos de estos identificadores.
Al correr la aplicación, el identificador quedará guardado en tu archivo R.java. Si abres y ves
su contenido, encontrarás el identificador dentro de la clase anidada id, con un valor entero
único asignado.
Parámetros De Un Layout
Los parámetros de un layout son atributos especiales que determinan como se relacionan
los hijos de un ViewGroup dependiendo de su posición y tamaño.
Estos se escriben de la forma layout_parametro para someter al view en cuestión.
Programáticamente se representan como una clase interna
llamada ViewGroup.LayoutParams.
Dependiendo de la jerarquía encontrada en el layout, así mismo se aplican los parámetros:
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
El resultado:
Ejemplo De FrameLayout
El parámetro gravitiy se basa en las posiciones comunes de un view dentro del layout. Se
describe con constantes de orientación:
top: Indica la parte superior del layout.
left: Indica la parte izquierda del layout.
right: Se refiere a la parte derecha del layout.
bottom: Representa el límite inferior del layout.
center_horizontal: Centro horizontal del layout.
center_vertical: Alineación al centro vertical del layout.
center: Es la combinación de center_horizontal y center_vertical.
Como se muestra en la ilustración, es posible crear variaciones combinadas, como por
ejemplo right + bottom. En código esta combinación puedes representarla con un OR
inclusivo.
android:layout_gravity="right|bottom"
<FrameLayout 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"
tools:context=".ActividadPrincipal">
<Button
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Saltar"
android:id="@+id/boton_saltar"
android:layout_gravity="center_horizontal|bottom"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/imagen_background"
android:layout_gravity="top|center"
android:src="@drawable/background_frame_layout"
android:scaleType="centerCrop" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imagen_estadistica"
android:layout_gravity="center"
android:src="@drawable/ejemplo_estadistica"
android:padding="16dp" />
</FrameLayout>
Ejemplo De LinearLayout
Un LinearLayout es un view group que distribuye sus hijos en una sola dimensión
establecida. Es decir, o todos organizados en una sola columna (vertical) o en una sola fila
(horizontal). La orientación puedes elegirla a través del atributo android:orientation.
android:weightSum="6"
Para distribuir todos los elementos sobre el espacio total del layout, puedes usar el atributo
height con valor cero.
android:layout_height="0dp"
android:layout_weight="3"
Si no lo haces, el relleno del espacio se definirá por las alturas que tú hayas definido, lo que
tal vez no complete el espacio total.
Ejmeplo
<TextView
android:id="@+id/texto_conectar"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:text="Conectar"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="@+id/input_usuario"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:hint="Correo" />
<EditText
android:id="@+id/input_contrasena"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:ems="10"
android:hint="Contraseña"
android:inputType="textPassword" />
<Button
android:id="@+id/boton_iniciar_sesion"
style="?android:attr/buttonStyleSmall"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:text="Iniciar Sesion" />
<TextView
android:id="@+id/texto_olvidaste_contrasena"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="¿Olvidaste tu constraseña?"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#0E8AEE" />
</LinearLayout>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ejemplo_frame_layout);
}
EJEMPLO DE RELATIVELAYOUT
Este elemento es el más flexible y elaborado de
todos los view groups que veremos.
El RelativeLayout permite alinear cada hijo con
referencias subjetivas de cada hermano.
¿Qué significa esto?
Con el RelativeLayout pensaremos en como
alinear los bordes de cada view con otros. Imagina
en una sentencia como “el botón estará por debajo
del texto” o “la imagen se encuentra a la derecha
de la descripción”.
En ninguno de los casos nos referimos a una
posición absoluta o un espacio determinado.
Simplemente describimos la ubicación y el
framework de Android computará el resultado
final.
<span class="tag"><Button</span>
<span class="atn">...</span>
<span class="atn">android:layout_below</span><span
class="pun">=</span><span class="atv">"@+id/editor_nombre"</span><span
class="tag">/></span>
<EditText
android:id="@+id/input_apellido"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/input_nombre"
android:ems="10"
android:hint="Apellidos"
android:inputType="textPersonName" />
<TextView
android:id="@+id/texto_estado_civil"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/input_apellido"
android:layout_marginRight="48dp"
android:paddingBottom="8dp"
android:paddingTop="16dp"
android:text="Estado civil"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Spinner
android:id="@+id/spinner_estado_civil"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/texto_estado_civil"
android:layout_toLeftOf="@+id/spinner_cargo"
android:entries="@array/lista_estado_civil" />
<TextView
android:id="@+id/texto_cargo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/input_apellido"
android:layout_centerHorizontal="true"
android:layout_toRightOf="@+id/texto_estado_civil"
android:paddingBottom="8dp"
android:paddingTop="16dp"
android:text="Cargo"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Spinner
android:id="@+id/spinner_cargo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/texto_cargo"
android:layout_alignParentRight="true"
android:layout_alignStart="@+id/texto_cargo"
android:layout_below="@+id/texto_cargo"
android:entries="@array/lista_cargo" />
</RelativeLayout>
Para crear las filas se usa el componente TableRow dentro del TableLayout. Cada celda es
declarada como un view de cualquier tipo (imagen, texto, otro group view, etc.) dentro de
la fila. Sin embargo, puedes crear una celda con otro tipo de view. Esto hará que todo el
espacio de la fila sea ocupado por el objeto.
El TableRow trae consigo un parámetro llamado android:layout_column para asignar la
columna a la que pertenece cada celda en su interior. Incluso puedes usar el
parámetro weight para declarar pesos de las celdas.
El ancho de cada columna es definido tomando como referencia la celda más ancha. Pero
también podemos definir el comportamiento del ancho de las celdas con los siguientes
atributos:
android:shrinkColumns: Reduce el ancho de la columna seleccionada hasta ajustar la fila al
tamaño del padre.
android:stretchColumns: Permite rellenar el espacio vacío que queda en el TableLayout,
expandiendo la columna seleccionada.
A continuación crearemos una prueba.
Paso 1. Crea un nuevo archivo dentro de res/layout con el nombre
de ejemplo_table_layout.xml. Esta vez verás el diseño de una factura en forma de tabla.
Habrá una columna para los productos y otra para representar el subtotal.
Al final de los ítems pondremos una línea divisoria y por debajo calcularemos la cuenta total.
<TableRow android:background="#128675">
<TextView
android:layout_column="0"
android:padding="3dip"
android:text="Producto"
android:textColor="@android:color/white" />
<TextView
android:layout_column="2"
android:padding="3dip"
android:text="Subtotal"
android:textColor="@android:color/white" />
</TableRow>
<TableRow>
<TextView
android:layout_column="0"
android:padding="3dip"
android:text="Jabón de manos x 1" />
<TextView
android:layout_column="2"
android:gravity="left"
android:padding="3dip"
android:text="$2" />
</TableRow>
<TableRow>
<TextView
android:layout_column="0"
android:padding="3dip"
android:text="Shampoo Monster x 1" />
<TextView
android:layout_column="2"
android:gravity="left"
android:padding="3dip"
android:text="$10" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:padding="3dip"
android:text="Pastas Duria x 2" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:gravity="left"
android:padding="3dip"
android:text="$18" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:padding="3dip"
android:text="Detergente Limpiadin x 1" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:gravity="left"
android:padding="3dip"
android:text="$13,4" />
</TableRow>
<View
android:layout_height="2dip"
android:background="#FF909090" />
<TableRow>
<TextView
android:layout_column="1"
android:padding="3dip"
android:text="Subtotal"
android:textColor="#128675" />
<TextView
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_gravity="left"
android:gravity="right"
android:padding="3dip"
android:text="$43,4" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:padding="3dip"
android:text="Costo envío"
android:textColor="#128675" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_gravity="left"
android:gravity="right"
android:padding="3dip"
android:text="$10" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:padding="3dip"
android:text="Cupón"
android:textColor="#128675" />
<TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_gravity="left"
android:gravity="right"
android:padding="3dip"
android:text="-$5" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:padding="3dip"
android:text="Total"
android:textColor="#128675" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_gravity="left"
android:gravity="right"
android:padding="3dip"
android:text="$48,4" />
</TableRow>
</TableLayout>
<TextView
android:id="@+id/celda_1"
android:layout_columnSpan="2"
android:layout_rowSpan="3"
android:text="Celda 1" />
En la ilustración mostrada al inicio, existe una cuadrícula de 8×4 con 5 views. Sus atributos
span se encuentran escritos en de la forma axb.
Como ves, es posible expandir las celdas de forma horizontal y vertical. Incluso es posible
proyectar views de forma cruzada.
Si observas bien, el elemento que se encuentra en la segunda fila con las especificaciones
1×2 se cruza en la columna 3. Esto se debe a que su ancho es de 3 unidades, per su
atributo columnSpan es igual a 2, lo que facilita al framework crear el cruce si existe espacio
en blanco.
También puedes especificar a qué fila y columna pertenece cada view con los
atributos android:layout_row y android:layout_column.
El siguiente TextView se encuentra en la posición (0,0).
<TextView
android:id="@+id/celda_1"
android:layout_column="0"
android:layout_row="0"
android:text="Celda 1" />
ejemplo
<TextView
android:id="@+id/numero_7"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_column="0"
android:layout_row="0"
android:text="7" />
<TextView
android:id="@+id/numero_8"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_row="0"
android:text="8" />
<TextView
android:id="@+id/numero_9"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_row="0"
android:text="9" />
<TextView
android:id="@+id/numero_4"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_row="1"
android:text="4" />
<TextView
android:id="@+id/numero_5"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_row="1"
android:text="5" />
<TextView
android:id="@+id/numero_6"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_row="1"
android:text="6" />
<TextView
android:id="@+id/signo_por"
style="@style/AppTheme.BotonCalculadora.Rojo"
android:layout_column="3"
android:layout_gravity="fill"
android:layout_row="1"
android:gravity="center"
android:text="×" />
<TextView
android:id="@+id/textView10"
style="@style/AppTheme.BotonCalculadora.Rojo"
android:layout_column="3"
android:layout_gravity="fill_horizontal"
android:layout_row="0"
android:text="÷" />
<TextView
android:id="@+id/numero_1"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_column="0"
android:layout_row="2"
android:text="1" />
<TextView
android:id="@+id/numero_2"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_row="2"
android:text="2" />
<TextView
android:id="@+id/numero_3"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_row="2"
android:text="3" />
<TextView
android:id="@+id/signo_menos"
style="@style/AppTheme.BotonCalculadora.Rojo"
android:layout_column="3"
android:layout_gravity="fill_horizontal"
android:layout_row="2"
android:gravity="center"
android:text="-" />
<TextView
android:id="@+id/punto"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_column="0"
android:layout_gravity="fill_horizontal"
android:layout_row="3"
android:gravity="center_horizontal"
android:text="." />
<TextView
android:id="@+id/cero"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_column="1"
android:layout_row="3"
android:text="0" />
<TextView
android:id="@+id/signo_igual"
style="@style/AppTheme.BotonCalculadora.Azul"
android:layout_column="2"
android:layout_gravity="fill_horizontal"
android:layout_row="3"
android:text="=" />
<TextView
android:id="@+id/signo_mas"
style="@style/AppTheme.BotonCalculadora.Rojo"
android:layout_column="3"
android:layout_gravity="fill_horizontal"
android:layout_row="3"
android:text="+" />
</GridLayout>
<style name="AppTheme.BotonCalculadora"
parent="TextAppearance.AppCompat.Headline">
<item name="android:textColor">@android:color/white</item>
<item name="android:gravity">center</item>
<item name="android:padding">36dp</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
En la vista de diseño tendremos una sección llamada Palette, la cual contiene todos los
elementos gráficos posibles que podemos implementar dentro de un layout. Desde este
lugar puedes seleccionar cualquier elemento y arrastrarlo al lienzo. Dentro de esta existen
varias categorías, como Layouts, donde se encuentran los layouts que hemos visto hasta
ahora.
El lienzo es simplemente la representación visual en tiempo real de la interfaz de la
aplicación. Cuando arrastras un elemento de la paleta hacia el lienzo, este proyecta guías
visuales para indicarte como será acomodado el view si lo sueltas en esa posición.
El panel de propiedades (Properties) muestra los atributos del view seleccionado. En el
veremos una lista con pares clave-valor para escoger las opciones que deseamos sin ver el
código XML.
Cambiar versión de Android— En las variaciones del editor visual, podemos cambiar la
versión de Android con que se está mostrando el layout actual.
Esto con el fin de comprobar que los diseños funcionen de forma integral en versiones
anteriores.
Para ello dirígete al icono del androide en la parte superior derecha y despliega la lista de
versiones disponibles. Selecciona la que desees y analiza el cambio.
Si presionas la opción Preview Android Versions se desplegarán al mismo tiempo varios
layouts con el diseño actual.
Visualizar layouts con múltiples idiomas— Si tienes traducciones para los strings
relacionados a tus layouts, entonces puedes las respectivas variaciones con la opción del
globo.
La ilustración anterior muestra que existe un recurso strings para el idioma inglés, por lo
que al presionar la opción Preview All Locales veremos las variaciones en pantalla.
Variar el tema del layout— Otro cambio que puedes realizar, es la selección de un tema
distinto para el renderizado del layout. Solo presiona el icono parecido a un eclipse.
Esto despliega un asistente con la lista de todos los estilos que tiene el sistema. Elige el que
desees probar y confirma.
Por otro lado, si eliges la opción Preview All Screen Sizes, Android Studio proyectará el
layout en todos los dispositivos disponibles.
Crear variación landscape de un layout— En ocasiones los layout que creamos suelen
desajustarse al momento de rotar la pantalla a landscape. Esto afecta la experiencia de
usuario, ya que desaprovecha el espacio de acción y es posible que los views pierdan
congruencia.
Un pequeño ejemplo de esta situación podemos verlo al
rotar ejemplo_relative_layout.xml a landscape.
Debido a que el espacio horizontal casi es duplicado, el EditText para los nombres se ve
forzado. Una de las ideas para mejorar el diseño, podría ser mover el edit Text de apellidos
a la derecha para compensar.
Solucionaremos esto creando un layout especial para orientación horizontal, donde
haremos el cambio. Ve a la primera opción donde se ve un icono de un archivo junto al logo
de android. Esto desplegará una lista de varias opciones, pero la que nos interesa es Create
Landscape Variation.
<EditText
android:id="@+id/input_nombre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginRight="48dp"
android:ems="10"
android:hint="Nombres"
android:inputType="textPersonName" />
<EditText
android:id="@+id/input_apellido"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/input_nombre"
android:ems="10"
android:hint="Apellidos"
android:inputType="textPersonName" />
<TextView
android:id="@+id/texto_estado_civil"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/input_apellido"
android:paddingBottom="8dp"
android:paddingTop="16dp"
android:text="Estado civil"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Spinner
android:id="@+id/spinner_cargo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/texto_estado_civil"
android:layout_toLeftOf="@+id/spinner_estado_civil"
android:entries="@array/lista_cargo" />
<TextView
android:id="@+id/texto_cargo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/input_apellido"
android:layout_below="@+id/input_apellido"
android:paddingBottom="8dp"
android:paddingTop="16dp"
android:text="Cargo"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Spinner
android:id="@+id/spinner_estado_civil"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/texto_cargo"
android:layout_alignParentRight="true"
android:layout_alignStart="@+id/texto_cargo"
android:layout_below="@+id/texto_cargo"
android:entries="@array/lista_estado_civil" />
</RelativeLayout>