Curso Android
No es la forma recomendable para trabajar.
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
TextView texto = new TextView(this);
texto.setText("Hello, Android");
setContentView(texto);
}Ejemplo
La interfaz de usuario de Android está basada en una jerarquía de clases descendientes de la clase View (vista).
Una vista es un objeto que se puede dibujar y se utiliza como un elemento en el diseño de la interfaz de usuario (un botón, una imagen, una etiqueta de texto como en el utilizado en el ejemplo, etc.).
Cada uno de estos elementos se define como una subclase de la clase View; la subclase para representar un texto es TextView.
El ejemplo comienza creando un objeto de la clase TextView. El constructor de la clase acepta como parámetro una instancia de la clase Context (contexto).
Un contexto es un manejador del sistema que proporciona servicios como la resolución de recursos, obtención de acceso a bases de datos o preferencias.
La clase Activity es una subclase de Context, y como la clase MainActivity es una subclase de Activity, también es de tipo Context. Por ello, puedes pasar this (el objeto actual de la clase MainActivity) como contexto del TextView.
A veces puede ser muy complicado programar interfaces de usuario, ya que pequeños cambios en el diseño pueden corresponder a complicadas modificaciones en el código.
Android proporciona una alternativa para el diseño de interfaces de usuario: los ficheros de diseño basados en XML.
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout><resources>
<string name="app_name">My Application</string>
<string name="hello_world">Hello World!</string>
</resources>public final class R {
public static final class attr {
}
public static final class dimen {
public static final int activity_horizontal_margin=0x7f040000;
public static final int activity_vertical_margin=0x7f040001;
}
public static final class drawable {
public static final int ic_launcher=0x7f020000;
}
public static final class id {
public static final int action_settings=0x7f080001;
public static final int texto1=0x7f080000;
}
public static final class layout {
public static final int activity_main=0x7f030000;
}
public static final class menu {
public static final int main=0x7f070000;
}
public static final class string {
public static final int action_settings=0x7f050001;
public static final int app_name=0x7f050000;
public static final int hello_world=0x7f050002;
public static final int hola_mundo=0x7f050003;
}
public static final class style {
public static final int AppBaseTheme=0x7f060000;
public static final int AppTheme=0x7f060001;
}
}Todas estas estructuras XML serán leidas cuando la aplicación arranque …. pero como nos encontramos en una plataforma movil el trabajo con XML directo podría ser demoledor y lento .
Por lo tanto Android despues de leer el fichero XML carga todas las estructuras que se han solicitado en memoria y mantiene el fichero R como referencia directa a los recursos que se han cargado de esta manera el acceso será directo y sencillo para el programador.
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView texto1= (TextView) findViewById(R.id.texto1);
texto1.setText(R.string.world);
}
}<resources>
<string name="app_name">HolaMundo</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="hola_mundo">Hola Mundo</string>
</resources><TextView android:id="@+id/texto1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />setContentView(R.layout.activity_main) ;
Aquí, R.layout.activity_main corresponde a un objeto View que será creado en tiempo de ejecución a partir del recurso activity_main.xml. Trabajar de esta forma, en comparación con el diseño basado en código, no quita velocidad y requiere menos memoria. Este identificador es creado automáticamente en la clase R del proyecto a partir de los elementos de la carpeta res.
Los identificadores de la clase R son meros números que informan al gestor de recursos, que datos ha de cargar. Por lo tanto no se trata de verdaderos objetos, estos serán creados en tiempo de ejecución solo cuando sea necesario usarlos.
Tamaño de pantalla
Densidad de pantalla
Orientación
Resolución
En muchas ocasiones tenemos que indicar la anchura o altura de una vista, un margen, el tamaño de un texto o unas coordenadas. Este tipo de atributos se conocen como atributos de dimensión.
Android nos permite indicar estas dimensiones de varias formas.
px (píxeles): Estas dimensiones representan los píxeles en la pantalla.
mm (milímetros): Distancia real medida sobre la pantalla.
in (pulgadas): Distancia real medida sobre la pantalla.
pt (puntos): Equivale a 1/72 pulgadas.
dp (Píxeles independientes de la densidad)
El píxel independiente de la densidad es equivalente a un píxel físico en una pantalla de 160 dpi, valor que representa la densidad de referencia que considera el sistema para una pantalla de densidad “media”. En el tiempo de ejecución, el sistema maneja de forma transparente cualquier ajuste de las unidades dp, cuando resulta necesario, según la densidad actual de la pantalla en uso. La conversión de unidades dp a píxeles de pantalla es simple: px = dp * (dpi / 160). Por ejemplo, en una pantalla de 240 dpi, 1 dp es igual a 1,5 píxeles físicos. Siempre debes usar unidades dp cuando defines la IU de tu aplicación, para asegurarte de que tu IU se muestre de manera apropiada en pantallas con diferentes densidades.
sp (píxeles escalados): Similar a dp, pero también se escala en función del tamaño de fuente que el usuario ha escogido en las preferencias. Indicado cuando se trabaja con fuentes.
LinearLayout: Dispone los elementos en una fila o en una columna.
TableLayout: Distribuye los elementos de forma tabular.
RelativeLayout: Dispone los elementos en relación a otro o al padre.
AbsoluteLayout: Posiciona los elementos de forma absoluta.
FrameLayout: Permite el cambio dinámico de los elementos que contiene.
ConstraintLayout: Versión mejorada de RelativeLayout, que permite una edición visual desde el editor y trabajar con porcentajes.
Permite comenzar a situar los elementos en cualquiera de los cuatro lados del contenedor e ir añadiendo nuevos elementos pegados a estos.
<RelativeLayout
xmlns:android="http://schemas...
android:layout_height="match_parent"
android:layout_width="match_parent">
<AnalogClock
android:id="@+id/AnalogClock01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"/>
<CheckBox
android:id="@+id/CheckBox01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/AnalogClock01"
android:text="Un checkBox"/>
<Button
android:id="@+id/Button01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un botón"
android:layout_below="@id/CheckBox01"/>
<TextView
android:id="@+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Un texto cualquiera"/>
</RelativeLayout>Es uno de los Layout más utilizado en la práctica. Distribuye los elementos uno detrás de otro, bien de forma horizontal o vertical.
<LinearLayout xmlns:android="http://...
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation ="vertical">
<AnalogClock
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un checkBox"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un botón"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un texto cualquiera"/>
</LinearLayout>Distribuye los elementos de forma tabular. Se utiliza la etiqueta <TableRow> cada vez que queremos insertar una nueva línea.
<TableLayout xmlns:android=”http://...
android:layout_height="match_parent"
android:layout_width="match_parent">
<TableRow>
<AnalogClock
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un checkBox"/>
</TableRow>
<TableRow>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un botón"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un texto cualquiera"/>
</TableRow>
</TableLayout>Permite indicar las coordenadas (x,y) donde queremos que se visualice cada elemento. No es recomendable utilizar este tipo de Layout. De hecho, este tipo de Layout ha sido marcado como obsoleto.
<AbsoluteLayout xmlns:android="http://schemas.
android:layout_height="match_parent"
android:layout_width="match_parent">
<AnalogClock
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="50px"
android:layout_y="50px"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un checkBox"
android:layout_x="150px"
android:layout_y="50px"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un botón"
android:layout_x="50px"
android:layout_y="250px"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un texto cualquiera"
android:layout_x="150px"
android:layout_y="200px"/>
</AbsoluteLayout>Posiciona las vistas usando todo el contenedor, sin distribuirlas espacialmente. Este Layout suele utilizarse cuando queremos que varias vistas ocupen un mismo lugar. Podemos hacer que solo una sea visible, o superponerlas.
<FrameLayout xmlns:android="http://schemas...
android:layout_height="mach_parent"
android:layout_width="match_parent">
<AnalogClock
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un checkBox"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un botón"
android:visibility="invisible"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Un texto cualquiera"
android:visibility="invisible"/>
</FrameLayout>ScrollView: Visualiza una columna de elementos; cuando estos no caben en pantalla se permite un deslizamiento vertical.
HorizontalScrollView: Visualiza una fila de elementos; cuando estos no caben en pantalla se permite un deslizamiento horizontal.
FragmentTabHost, TabLayout ó TabHost: Proporciona una lista de ventanas seleccionables por medio de etiquetas que pueden ser pulsadas por el usuario para seleccionar la ventana que desea visualizar.
ListView: Visualiza una lista deslizable verticalmente de varios elementos. Su utilización es algo compleja.
GridView: Visualiza una cuadrícula deslizable de varias filas y varias columnas.
RecyclerView: Versión actualizada que realiza las mismas funciones que ListView o GridView.
ViewFlipper: Permite visualizar una lista de elementos de forma que se visualice uno cada vez. Puede ser utilizado para intercambiar los elementos cada cierto intervalo de tiempo.
Guía para el diseño visual de las aplicaciones, que Google no quiere aplicar exclusivamente a dispositivos móviles, sino que pretende utilizar material design en todo tipo de contenidos digitales
Uno de los principios que se definen en Material Design es el uso del color. Google propone usar colores vivos y alegres.
Una aplicación Android va a poder ser ejecutada en una gran variedad de dispositivos. El tamaño de pantalla, la resolución o el tipo de entradas puede variar mucho de un dispositivo a otro. Por otra parte, nuestra aplicación ha de estar preparada para diferentes modos de funcionamiento, como el modo “automóvil” o el modo “noche”, y para poder ejecutarse en diferentes idiomas.
Afortunadamente, la plataforma Android nos proporciona una herramienta de gran potencia para resolver este problema: el uso de los recursos alternativos.
Android utiliza una lista de sufijos para expresar recursos alternativos. Estos sufijos pueden hacer referencia a la orientación del dispositivo, al lenguaje, la región, la densidad de píxeles, la resolución, el método de entrada,…
Por ejemplo, si queremos traducir nuestra aplicación al inglés, español y francés. Siendo el primer idioma el usado por defecto, crearíamos tres versiones del fichero strings.xml y lo guardaríamos en los siguientes tres directorios:
res/values/strings.xml
res/values-es/strings.xml
res/values-fr/strings.xml
Aunque internamente el SDK de Android utiliza la estructura de carpetas anterior, en Android Studio el explorador del proyecto muestra los recursos alternativos de la siguiente manera:
res
values
strings.xml(3)
strings.xml
strings.xml(es)
strings.xml(fr)
Crea un nuevo recurso alternativo para strings.xml (en):
Otro ejemplo de utilización de recursos diferenciados lo podemos ver con el icono que se utiliza para lanzar la aplicación. Observa como, al crear una aplicación, este icono se crea en cinco carpetas drawable diferentes, para utilizar un icono distinto según la densidad de píxeles del dispositivo:
res/mipmap-mdpi/ic_launcher.png
res/mipmap-hdpi/ic_launcher.png
res/mipmap-xhdpi/ic_launcher.png
res/mipmap-xxhdpi/ic_launcher.png
res/mipmap-xxxhdpi/ic_launcher.png
Añadir un recurso a nuestra aplicación es muy sencillo, no tenemos más que añadir un fichero dentro de una carpeta determinada de nuestro proyecto. Para cada uno de los recursos que añadamos el sistema crea, de forma automática, un id de recurso dentro de la clase R.
|
Carpeta |
Descripción
|
|
res/drawable/ |
Ficheros en bitmap (.png, .jpg o .gif). Ficheros PNG en formato Nine-patch (.9.png). Ficheros XML con descriptores gráficos (ver clase Drawable) |
| res/mipmap/ R.mipmap |
Ficheros en bitmap (.png, .jpg o .gif). Estos gráficos no son rescaldados para adaptarlos a la densidad gráfica del dispositivo, sino que se buscará en las subcarpetas el gráfico con la densidad más parecida y se utilizará directamente. |
|
res/layout/ |
Ficheros XML con los Layouts usados en la aplicación. |
|
res/menu/ |
Ficheros XML con la definición de menús. Podemos asignar una actividad o una vista. |
|
res/anim/ |
Fichero XML que permiten definir una animaciones Tween también conocidas como animaciones de vista. |
|
res/animator |
Ficheros XML que permiten modificar las propiedades de un objeto a lo largo del tiempo. (Véase apartado "Animación de propiedades"). Solo desde la versión 3.0. |
|
res/xml/ |
Otros ficheros XML, como los ficheros de preferencias |
|
res/raw/ |
Ficheros que se encuentran en formato binario. Por ejemplo ficheros de audio o vídeo. |
|
res/values/ |
Ficheros XML que definen un determinado valor para definir un color, estilo, cadena de caracteres, etc. Se describen en la siguiente tabla. |
|
Fichero por defecto |
Descripción |
|
strings.xml |
Identifica cadenas de caracteres <string name="saludo">¡Hola Mundo!</string> |
|
colors.xml |
Un color definido en formato ARGB (alfa, rojo, verde y azul). Los valores se indican en hexadecimal en uno de los siguientes formatos: #RGB, #ARGB, #RRGGBB ó #AARRGGBB <color name="verde_opaco">#0f0</color>
|
|
dimensions.xml |
Un número seguido de una unidad de medida. px - pixeles, mm - milímetros, in – pulgadas, pt – puntos (=1/72 pulgadas), dp – píxeles independientes de la densidad (=1/160 pulgadas), sp – igual que dp pero cambia según las preferencias de tamaño de fuente. <dimen name="alto">2.2mm</dimen>
|
|
styles.xml
|
Definen una serie de atributos que pueden ser aplicados a una vista o a una actividad. Si se aplican a una actividad se conocen como temas. <style name="TextoGrande" parent="@style/Text">
|
|
|
|
R.int |
Define un valor entero. <integer name="max_asteroides">5</integer> |
|
R.bool |
Define un valor booleano. <bool name="misiles_ilimitados">true</bool> |
|
R.id |
Define un recurso de id único. La forma habitual de asignar id a los recursos es utilizando el atributo id="@+id/nombre". Aunque en algunos casos puede ser interesante disponer de id previamente creado, para que los elementos así nombrados tengan una determinada función. Este tipo de id se utiliza en las vistas TabHost y ListView. <item type="id" name="button_ok"/> |
|
R.array |
Una serie ordenada de elementos. Pueden ser de strings, de enteros o de recursos (TypedArray) <string-array name="dias_semana"> <item>lunes</item> <integer-array name="primos"> |
<ImageView
android:layout_height="@dimen/alto"
android:layout_width="match_parent"
android:background="@drawable/asteroide"
android:text="@string/saludo"
android:text_color="@color/verde_opaco"/>
Para acceder a un recurso definido en los ejemplos anteriores desde Java usaremos el siguiente código:
Resources res =getResources();
Drawable drawable =res.getDrawable(R.drawable.asteroide);
String saludo = res.getString(R.string.saludo);
int color =res.getColor(R.color.verde_opaco);
float tamanoFuente =res.getDimension(R.dimen.tamano_fuente);
int maxAsteroides =res.getInteger(R.integer.max_asteroides);
boolean ilimitados = res.getBoolean(R.bool.misiles_ilimitados);
String[] diasSemana =res.getStringArray(R.array.dias_semana);
int[] primos =res.getIntArray(R.array.primos);
TypedArray asteroides =res.obtainTypedArray(R.array.asteroides);
Drawable asteroide1 =asteroides.getDrawable(0);
Usar recursos del sistema tiene muchas ventajas.
Para acceder a los recursos del sistema desde código usaremos la clase android.R. Se utiliza la misma estructura de jerárquica de clases. Por ejemplo android.R.drawable.ic_menu_edit. Para acceder desde XML utiliza la sintaxis habitual pero comenzando con @android:. Por ejemplo @android:drawable/ic_menu_edit.
Un estilo es una colección de propiedades que definen el formato y apariencia que tendrá una vista. Podemos especificar cosas como tamaño, márgenes, color, fuentes, etc. Un estilo se define en ficheros XML, diferente al fichero XML Layout que lo utiliza.
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#00FF00"
android:typeface="monospace"
android:text="Un texto" /><TextView
style="@style/MiEstilo"
android:text="Un texto" /><?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MiEstilo"
parent="@android:style/TextAppearance.Medium">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#00FF00</item>
<item name="android:typeface">monospace</item>
</style>
</resources><style name="MiEstilo.grande">
<item name="android:textSize">18pt</item>
</style><style name="MiEstilo.grande.negrita">
<item name="android:textStyle">bold</item>
</style>Un tema es un estilo aplicado a toda una actividad o aplicación, en lugar de a una vista individual. Cada elemento del estilo solo se aplicará a aquellos elementos donde sea posible.
Para aplicar un tema a toda una aplicación edita el fichero AndroidManifest.xml y añade el parámetro android:theme en la etiqueta <application>:
<application android:theme="@style/MiTema">
También puedes aplicar un tema a una actividad en concreto:
<activity android:theme="@style/MiTema">
Además de crear tus propios temas vas a poder utilizar algunos disponibles en el sistema. Puedes encontrar una lista de todos los estilos y temas disponibles en Android en:http://developer.android.com/reference/android/R.style.html
Un control de tipo Button es el botón más básico que podemos utilizar y normalmente contiene un simple texto. En el ejemplo siguiente definimos un botón con el texto “Click” asignando su propiedad android:text. Además de esta propiedad podríamos utilizar muchas otras como el color de fondo (android:background), estilo de fuente (android:typeface), color de fuente (android:textcolor), tamaño de fuente (android:textSize), etc.
<Button android:id="@+id/BtnBotonSimple"
android:text="@string/click"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />Un control de tipo ToggleButton es un tipo de botón que puede permanecer en dos posibles estados, pulsado o no_pulsado. En este caso, en vez de definir un sólo texto para el control definiremos dos, dependiendo de su estado. Así, podremos asignar las propiedades android:textOn y android:textoOff para definir ambos textos. Veamos un ejemplo a continuación.
<ToggleButton android:id="@+id/BtnToggle"
android:textOn="@string/on"
android:textOff="@string/off"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />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:
<Switch android:id="@+id/BtnSwitch"
android:textOn="@string/on"
android:textOff="@string/off"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />En un control de tipo ImageButton podremos definir una imagen a mostrar en vez de un texto, para lo que deberemos asignar la propiedad android:src. Adicionalmente, al tratarse de un control de tipo imagen también deberíamos acostumbrarnos a asignar la propiedad android:contentDescription con una descripción textual de la imagen, de forma que nuestra aplicación sea lo más accesible posible.
<ImageButton android:id="@+id/BtnImagen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/icono_ok"
android:src="@drawable/ic_estrella" />Un control checkbox se suele utilizar para marcar o desmarcar opciones en una aplicación, y en Android está representado por la clase del mismo nombre, CheckBox.
<CheckBox android:id="@+id/ChkMarcame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/marcame"
android:checked="false" />
if (checkBox.isChecked()) {
checkBox.setChecked(false);
}Puede estar marcado o desmarcado, pero en este caso suelen utilizarse dentro de un grupo de opciones donde una, y sólo una, de ellas debe estar marcada obligatoriamente, es decir, que si se marca una de las opciones se desmarcará automáticamente la que estuviera activa anteriormente. En Android, un grupo de botones radio button se define mediante un elemento RadioGroup, que a su vez contendrá todos los elementos RadioButton necesarios.
<RadioGroup android:id="@+id/GrbGrupo1"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RadioButton android:id="@+id/RbOpcion1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/opcion_1" />
<RadioButton android:id="@+id/RbOpcion2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/opcion_2" />
</RadioGroup>RadioGroup rg = (RadioGroup)findViewById(R.id.GrbGrupo1);
rg.clearCheck();
rg.check(R.id.RbOpcion1);
int idSeleccionado = rg.getCheckedRadioButtonId();
El control ImageView permite mostrar imágenes en la aplicación.
<ImageView android:id="@+id/ImgFoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:contentDescription="@string/imagen_ejemplo" /><android.support.design.widget.TextInputLayout
android:id="@+id/TiLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<EditText android:id="@+id/TxtInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Escribe un número par" />
</android.support.design.widget.TextInputLayout>txtInputLayout = (TextInputLayout)findViewById(R.id.TiLayout);
txtInputLayout.setErrorEnabled(true);
txtInput = (EditText)findViewById(R.id.TxtInput);
btnComprobar = (Button)findViewById(R.id.BtnInputLayout);
btnComprobar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String num = txtInput.getText().toString();
if(num.isEmpty() || Integer.parseInt(num)%2 != 0)
txtInputLayout.setError("Error: No es un número par!");
else
txtInputLayout.setError(null);
}
});