Layouts de Android

Curso de Android

Contactar con el profesor

Primer proyecto

File → new → Android → Android Proyect → Create new proyect in Workspace → Lo llamamos a_hola_mundo

Esto crea un proyecto Android con un Activity que será el punto de inicio de la aplicación.

Error típico: An SDK Target must be specified → Para solventarlo → window → preferences → Android

Activity

Es una clase java. Presenta su propia interfaz de usuario (ventana).

Es cada una de las pantallas que componen una aplicación.

Uno de los activities es el que lanza la aplicación (lanzador)

Hola Mundo – Activity

Este es el código del Activity que se genera por defecto al crear nuestro proyecto.

public class A_holaMundoActivity extends Activity{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

R (resources) es una clase java (ruta gen/R.java) que contiene constantes que apuntan a la ubicación de los recursos utilizados en nuestra aplicación.

R.layout.main contiene la ubicación del XML que contiene la apariencia de nuestra activity. Está accesible desde res/layout/main.xml. En eclipse, será posible modificar dicha ubicación mediante un editor gráfico o mediante código.

Hola Mundo – Layout

Por defecto, la propiedad android:text del main.xml apunta a una variable hello, definida en res/values/string.xml que contiene su valor. También podría haber puesto directamente el texto “Hola Mundo”, en vez de una constante.

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
<TextView  
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
	android:text="@string/hello"

    />
</LinearLayout>

string.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, A_holaMundoActivity!</string>
    <string name="app_name">A_holaMundo</string>
</resources>

Unidades de medida

  • sp: scale-independent pixels. Es similar a la unidad dp, pero su tamaño variará dependiendo de las preferencias del usuario y de la densidad de la pantalla. Lo utilizarás para los tamaños de textos.
  • dp: density-independent pixels. Lo utilizarás para todo lo demás. Un dip es lo mismo que un dp, habitualmente utilizamos el término dp, porque se parece más al término sp. Estas unidades son relativas a una pantalla de 160 dpi(dots per inch); luego un dp equivale a un px en este tipo de pantalla.
  • px: pixel
  • in: inches (pulgadas). Basadas en el tamaño físico de la pantalla.
  • mm: milímetros. Basados en el tamaño físico de la pantalla.
  • pt: points. 1/72 de una pulgada.

Ejercicio Layout

Hacer una aplicación con un activity que llame a un layout llamado nuevo_layout.xml que tenga dos cuadros de texto.

En el primero se muestra el texto “Hola Mundo”. Dicho texto será una variable definida en strings.xml. Se mostrará en un tamaño superior al normal.

En el segundo se muestra el texto “Adios Mundo”. Dicho texto estará escrito directamente en la propiedad android:text. Se mostrará en rojo y en negrita.

Probar a introducir otros componentes, modificar sus propiedades y ver el efecto que esto tiene

Notas:

  • Para crear un nuevo layout: botón derecha sobre la carpeta res/layout en el panel de estructura de proyecto → new → Layout Resource File

Crear una interfaz de usuario por código

public class InterfazUSuarioActivity extends AppCompatActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView texto = new TextView(this);
        texto.setText("Hola Mundo");
        setContentView(texto);
    }
}

Al instanciar un objeto de la clase TextView le pasamos como parámetro el Activity que se va a encargar de gestionarlo.

La clase Activity es una subclase de Context.

El contexto es una variable que almacena el estado del teléfono (brillo, conectividad, batería…). Un activity y un servicio heredan de Context. Por tanto, también son contextos.

Como la clase InterfazUSuarioActivity es una subclase de Activity, también es de tipo context. Por ello, puedes pasar this como contexto del TextView.

Tipos de layout

  • Constraint (restricción) Layout
    Nota: Si tenemos algún elemento con su alto o ancho ocupando toda la pantalla o unas dimensiones demasiado grandes, los elementos desaparecerán por la derecha o el fondo de la pantalla.
  • Linear Layout
  • RelativeLayout: Los elementos se posicionan en función de los que tienen al lado. Ha sido sustituído por el Constraint Layout
  • FrameLayout
    Los elementos se superponen unos con otros. No es un layout típico.
  • TableLayout
    Coloca los elementos siguiendo una distribución de tabla
  • AbsoluteLayout
    Deprecated

Constraint Layout

Alineas cada vista en función de las que tienen al lado o de la que la envuelve.

Cada vista tiene al menos dos restricciones: horizontal y vertical. Estas restricción está conectada con el layout padre o una línea de guía invisible.

Generalmente, tenderemos a realizar este layout con las herramientas de la interfaz visual de android studio.

Añadiremos las restricciones (constraints) arrastrando y soltando a partir de los puntos azules ubicados en los cuatro puntos cardinales.

Layouts de Android 1

Linear Layout (el más frecuente)

Los elementos se irán apilando horizontal o verticalmente en función del parámetro orientation

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="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" />
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="un TextView" />
</LinearLayout>
Layouts de Android 2

Table Layout

Se utiliza la etiqueta TableRow cada vez que queremos insertar una nueva línea.
Utilizaré el atributo android:stretchColumns=”*” para que las celdas ajusten su tamaño hasta alcanzar los límites de la pantalla.

<?xml version="1.0" encoding="utf-8"?>
<TableLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="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 TextView" />
</TableRow>
</TableLayout>
Layouts de Android 3

GridLayout

<GridLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
      android:columnCount="2">
<AnalogClock 
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/un_checkbox" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content" 
android:text="@string/un_boton" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/un_textview" />
</GridLayout>
Layouts de Android 4

Frame Layout (posiciona todos los elementos usando todo el contenedor, sin distribuirlos espacialmente)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="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" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="un TextView" />
</FrameLayout>
Layouts de Android 5

Ejercicio Linear Layout

Utilizaremos un Linear Layout y setearemos su propiedad gravity.

El fichero res/strings.xml ha de tener el siguiente contenido:


<?xml version="1.0" encoding="utf-8"?>
<resources>
	<string name="app_name">Ejercicio Layout</string>
	<string name="pablomonteserin">Pablo Monteserín</string>
	<string name="menu1">Acerca de mí</string>
	<string name="menu2">Galería de videos</string>
	<string name="menu3">Galería de fotos</string>
	<string name="menu4">Contacto</string>
</resources>
Layouts de Android 6

Ejercicio: TableLayout

Android permite diseñar una vista diferente para la configuración horizontal y vertical.

A partir del ejercicio anterior, crea la carpeta res/layout-land y crea en ella una vista con el mismo nombre que la que está en la carpeta layout.

Para ver la carpeta land recién creada: panel Project → Packages.

Habrá que usar un TableLayout dentro de un LinearLayout. Para que los elementos del TableLayout ocupen todo el ancho de la celda, utilizar el siguiente atributo: android:stretchColumns=”*”.

Todos los elementos visuales del layout (los layouts, los Buttons y el TextView) deben tener un layout_width y un layout_height.

Layouts de Android 7

Ejercicio: strings.xml e internacionalizacion

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 pixeles, la resolución, etc.

Crea el siguiente fichero en el que traducirás todas las cadenas al inglés:
res/values-en/strings.xml

Para cambiar el idioma en el dispositivo:
Ajustes → Idioma y texto → Seleccionar idioma

Contenido scrollable

Bastará con envolver el Layout dentro de nuestro activity_main.xml por un ScrollView. El ScrollView sólo puede tener un hijo.

Ejercicio: Constraint Layout

Layouts de Android 8

AndroidManifest.xml

Describe las funcionalidades y los permisos que serán necesarios, etc. de la aplicación.
Para editarlo recurriremos a las vistas xml y no a las vistas gráficas que nos da eclipse.
Las siguientes líneas estarán contenidas en el nodo del activity que se lanzará en primer lugar al arrancar la aplicación:

<intent-filter>
	<action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

Cuando en la consola de trazas obtengo un “Class Not Found Exception”:
o el nombre de la clase o el nombre del paquete están mal en el manifest. Lo ideal es que en el manifest la definición del paquete coincida con el paquete raíz de todos los activities.

Si tenemos el siguiente error en las trazas:
android.content.ActivityNotFoundException: Unable to find explicit activity class…; have you declared this activity in your AndroidManifest.xml?

Falto declarar la segunda activity. Ponemos la siguiente línea en el AndroidManifest.xml

<activity android:name=".Second" />

R

Todos los recursos (xml, drawable, etc.) se empaquetan en un archivo R que es una especie de índice de recursos.

android:id=”@+id/item2″

La arroba significa que nos estamos refiriendo al archivo de recursos R.
El + significa que estamos añadiendo un nuevo recurso.

Cada vez q realizo un cambio en la estructura de mi proyecto (carpetas, documentos xml, atributos de dichos documentos, etc) android lo comprueba. Si el cambio arrojase un error es probable que dicho error apareciese reflejado en la pestaña Console

Imágenes

Tamaños de imágenes y layouts en función de la pantalla dónde serán reproducidos

res/drawable-mdpi/my_icon.png 		//bitmap for medium density
res/drawable-hdpi/my_icon.png 		//bitmap for high density
res/drawable-xhdpi/my_icon.png 		//bitmap for extra high density

res/layout/my_layout.xml 			//layout for normal screen size (“default”)
res/layout-small/my_layout.xml 		//layout for small screen size
res/layout-large/my_layout.xml 		//layout for large screen size
res/layout-xlarge/my_layout.xml 		//layout for extra large screen size
res/layout-xlarge-land/my_layout.xml 	//layout for extra large in landscape orientation

Ponemos los recursos en estas carpetas y será el sistema el que decida cuál utilizar.

Ejercicio: Cargar una imagen

Debemos copiar la imagen en la carpeta drawable-hdpi.

Cargar la imagen en un ImageView:
Introducimos un objeto de tipo ImageView en el xml y lo vinculamos a la imagen guardada en drawable.

Cargar la imagen en un ImageButton:
Introducimos un elemento de tipo ImageButton en el xml y lo vinculamos a la imagen guardada en drawable.

Cambiar dinámicamente la foto del ImageView anterior:

ImageView iv = findViewById(R.id.imageView1);
iv.setImageResource(R.drawable.cara);

Cargar imagen con esquinas redondeadas

ImageView iv = findViewById(R.id.miFoto);

Bitmap batmapBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.aperturaabductores);
RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), batmapBitmap);

// option 1 h/t [Chris Banes](https://chris.banes.me/)
circularBitmapDrawable.setCornerRadius(batmapBitmap.getWidth());

// option 2 h/t @csorgod in the comments
circularBitmapDrawable.setCircular(true);


iv.setImageDrawable(circularBitmapDrawable);
Layouts de Android 9

Background repeat

Por defecto una imagen se deformará para ocupar las dimensiones del ImageView, en el caso de que la imagen sea mas pequeña. Si lo que queremos es que la imagen se repita:

activity_main.xml<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/background_repeat"
...
background_repeat.xml<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android" 
   android:src="@drawable/icon"
   android:tileMode="repeat"
    />

Consola de trazas

Poner nuestras propias trazas:Log.d("total", cadenaTexto);

Si quiero mostrar por las trazas un número:

Log.d("total", ""+numeroRegistros);

Para ver las trazas:
Window → show view → other → logcat, devices (debo seleccionar el dispositivo del que quiero ver las trazas)

AndroidManifest.xml → Debbuggable: true

Ejercicios: estilos

Ejercicio – Cambiar dinámicamente el color o la imagen de fondo de un layout

LinearLayout milayout= findViewById(R.id.miLayout); 
milayout.setBackgroundColor(Color.rgb(151, 19, 19)); 

Ejercicio – Poner un degradado a un layout

res/drawable/degradado.xml
En el .java
View mlayout = findViewById(R.id.main_layout);
mlayout.setBackgroundResource(R.drawable.degradado);

Ejercicio: Maquetar un botón

res/drawable/rect.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="rectangle">
	<gradient
		android:startColor="#FFFF0000"
		android:endColor="#80FF00FF"
		android:angle="45"/>
	<!--  Este es el padding para colocar el texto -->
	<padding
		android:left="7dp"
		android:top="7dp"
		android:right="7dp"
		android:bottom="7dp" />		
	<corners android:radius="10dp" />
</shape>
main.xml
<Button android:text="Button"
 android:id="@+id/button1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="@drawable/rect" />
<Button android:text="Button"
 android:id="@+id/button1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" 
 android:background="@drawable/rect" />

Ejercicio; usar colores predefinidos

res/layout/main.xml
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    android:textSize="30dp"
    android:textColor="@color/red"
    />
res/values/colors.xml (o loquesea.xml)
<?xml version="1.0" encoding="utf-8"?>
<resources>
	<color name="red">#ff0000</color>
	<color name="green">#00ff00</color>
	<color name="blue">#0000ff</color>
</resources>

Ejercicio: Cargar las propiedades de un elemento desde un xml

es/layout/main.xml
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello" 
    style="@style/code"/>

Creamos el xml:
New → Android XML file → what type of resource would you like to create? → Values

res/values/styles.xml (o loquesea.xml)
<?xml version="1.0" encoding="utf-8"?>
<resources>
	<style name="code" parent="@android:style/TextAppearance">
		<item name="android:textSize">40sp</item>
		<item name="android:typeface">monospace</item>
		<item name="android:textColor">#0000FF</item>
	</style>    
</resources>

Ejercicio: Crear un estilo que sobrescriba el anterior

res/layout/loquesea.xml
<TextView 
    android:text="TextView" 
    android:id="@+id/textView1" 
    style="@style/code.red" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"></TextView>
res/values/styles.xml (o loquesea.xml)
<?xml version="1.0" encoding="utf-8"?>
<resources>
	<style name="code" parent="@android:style/TextAppearance">
			<item name="android:textSize">40sp</item>
			<item name="android:typeface">monospace</item>
			<item name="android:textColor">#0000FF</item>
	</style>
	<style name="code.red">
		<item name="android:textColor">#FF0000</item>
	</style>    
</resources>

Ejercicio Cargar un theme de los que vienen por defecto en android

Para aplicar un theme a toda la aplicación añado la línea en rojo en el AndroidManifest.xml:

<application android:icon="@drawable/icon" android:label="@string/app_name"
android:theme="@style/Base.Theme.AppCompat.Light">

Lo que no hacemos es aplicar el tema en el xml del layout.

No todos los temas son compatibles con todos los activities.

Para aplicarlo a un activity en concreto:

<activity android:name=".AcercaDe"
	android:label="@string/app_name"
	android:theme="@style/Base.Theme.AppCompat.Light"/>

Ejercicio: Cargar mi propio theme

New → Android XML file → what type of resource would you like to create? → Values

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style parent="@android:style/Theme.Dialog" name="myTheme">
    	<item name="android:textColor">#FF0000</item>
    </style>
</resources>

Cargamos el theme creado por nosotros utilizando el código pintado de rojo en el AndroidManifest.xml:


<application android:icon="@drawable/icon" android:label="@string/app_name"
android:theme="@style/myTheme">

Ejercicio : theme.dialog

Crear un theme que herede de Theme.Dialog y hacer que toda la aplicación lo implemente.

El tema tendrá los siguientes estilos:

android:textColor="#00FF00"
android:typeface="monospace"

Iconos

Recomendaciones sobre cómo hacer los iconos en Android

Fragments

Es una porción de la interfaz de usuario que puede añadirse o eliminarse forma independiente al resto de elementos de la actividad.

Esto nos permite dividir la interfaz en varias porciones con el fin de diseñar diversas configuraciones de pantalla.

Todo fragment debe tener asociado, además del layout, su propia clase java, que debe extender de la clase Fragment.

onCreateView(), es el “equivalente” al onCreate() de las actividades, y dentro de él es donde normalmente asignaremos un layout determinado al fragment. En este caso tendremos que “inflarlo” (convertir el XML en la estructura de objetos java equivalente) mediante el método inflate() pasándole como parámetro el ID del layout correspondiente, en nuestro caso fragment_listado.

activity_contiene_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.pablomonteserin.layouts.fragments.RecipienteFragment">

	<fragment class="com.pablomonteserin.layouts.fragments.BlankFragment"
        android:id="@+id/FrgListado"
        android:layout_weight="40"
        android:layout_width="match_parent"
        android:layout_height="60dp" />

</LinearLayout>
BlankFragment
public class BlankFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.layout_del_fragment, container, false);
    }
    @Override
    public void onActivityCreated(Bundle state) {
        super.onActivityCreated(state);
        TextView tv = getView().findViewById(R.id.elTextViewDelFragment);
        tv.setText("Esto es un fragment");
    }
}
layout_del_fragment.xml
<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="com.pablomonteserin.layouts.fragments.BlankFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment"
        android:id="@+id/elTextViewDelFragment"/>

</FrameLayout>

Tabs

layout_tabs.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <TabHost android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

            <TabWidget android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@android:id/tabs" />

            <FrameLayout android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@android:id/tabcontent" >

                <LinearLayout android:id="@+id/tab1"
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" >

                    <TextView android:id="@+id/textView1"
                        android:text="Contenido Tab 1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />
                </LinearLayout>

                <LinearLayout android:id="@+id/tab2"
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" >

                    <TextView android:id="@+id/textView2"
                        android:text="Contenido Tab 2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />
                </LinearLayout>
            </FrameLayout>
        </LinearLayout>
    </TabHost>
</LinearLayout>
Layouts de Android 10
TabsActivity
public class TabsActivity extends AppCompatActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.layout_tabs);

		Resources res = getResources();

		TabHost tabs=findViewById(android.R.id.tabhost);
		tabs.setup();

		TabHost.TabSpec spec=tabs.newTabSpec("mitab1");

		// Añado dos pestañas a mi sistema de pestañas. La primera ...
		spec.setContent(R.id.tab1);
		spec.setIndicator("", ContextCompat.getDrawable(this,android.R.drawable.ic_btn_speak_now));
		tabs.addTab(spec);

		//... y la segunda
		spec=tabs.newTabSpec("mitab2");
		spec.setContent(R.id.tab2);
		spec.setIndicator("mi casa es tu casa",ContextCompat.getDrawable(this, android.R.drawable.ic_dialog_email));
		tabs.addTab(spec);

		tabs.setCurrentTab(0);
    }
}

OnClick

 
main.xml
…
<Button android:text="Button"
 android:id="@+id/button1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:onClick="btnPulsado"/>
...
MainActivity.java
public void btnPulsado(View v){
	TextView tv = findViewById(R.id.textView1);
	tv.setText("botón pulsado");
}

Clase OnClickListener

Con esto conseguiremos tener solamente una única clase que gestione todos los eventos de click.

public class Main extends AppCompatActivity{
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
        
		Button b = findViewById(R.id.button1);
		b.setOnClickListener(new View.OnClickListener(){

			@Override
			public void onClick(View v) {
				Log.d("traza", "llega");
			}
		});
	}
}

Añadir un nuevo Activity

Botón derecho sobre el paquete → new → Activity → Empty Activity

Esto crea una clase Activity con su método onCreate y su correspondiente referencia en el AndroidManifest.xml.

¿Para qué sirve un Intent?

Para invocar componentes (un Activity, código ejecutándose en segundo plano, et.)

Crear un botón en la primera activity para que cuando pulsemos sobre él vayamos a la segunda

startActivity(new Intent(this, SecondActivity.class));

Activity que hace la llamada. Si sólo ponemos this, se pensará que estamos haciendo referencia a la clase OnClickListener, en lugar de a la clase Main

Hay que registrar el Activity en el AndroidManifest.xml
<activity android:name=".AcercaDe" 
android:label="@string/app_name">
</activity>

Pasar información de una activity a otra

En el editor visual de layouts de Android, un componente Plain Text corresponde realmente a un EditText en el código fuente.

Main.java
	public final static String TEXTO = "texto";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	public void pasarInfo(View view) {
		final EditText et = findViewById(R.id.editText1);
		Intent intent = new Intent(this, SecondActivity.class);
		intent.putExtra(TEXTO, et.getText().toString());
		startActivity(intent);
	}
SecondActivity.java
public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.second);
		TextView tv = findViewById(R.id.textView1);
		tv.setText(getIntent().getExtras().getString(Main.TEXTO));
	}

Ejercicio: Crear un menú

Un menú contextual es lanzado al pulsar la tecla menú del teléfono.

res/menu/menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:id="@+id/item1" android:title="Option 1" android:icon="@android:drawable/ic_menu_compass" />
	<item android:id="@+id/item2" android:title="Option 2" android:icon="@android:drawable/ic_menu_call" />    
</menu>
MenuActivity.java
public class MenuActivity extends Activity {
	...
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}

Al ejecutar la aplicación pulsamos el botón de menú para ver los menús.

Layouts de Android 11

Ejercicio: Detectar la pulsación de un menú

Añadimos el siguiente código al java anterior:


public boolean onOptionsItemSelected(MenuItem item){
	if(item.getItemId() == R.id.item1){
    	Log.d("opcion", "opcion 1 pulsada");
    }
	return super.onOptionsItemSelected(item);
}

También se podía haber hecho con el método onclick, procesando la información de la siguiente forma:

public void menuPulsado(MenuItem menu){
	...
}

Problema al cambiar la orientación de la pantalla

Al cambiar la orientación se destruyen los componentes visuales y se vuelven a crear, llamando al onCreate.

Podemos solventar los problemas que esto pueda acarrear modificando el nodo <activity> correspondiente del AndroidManifest.xml:

– Para limitar el giro de la aplicación:
android:screenOrientation=”portrait”

– Para que no se destruya el activity:
android:configChanges=”keyboard | keyboardHidden | orientation | screenSize | smallestScreenSize”

Ejercicio: Al pulsar sobre un botón, convertir una imagen en otra

Asignaremos el xml de la animación al imageview usando el atributo src del layout.

MainActivity.java
ImageView iv = findViewById(R.id.imageView1);
TransitionDrawable td = (TransitionDrawable) iv.getDrawable();
td.startTransition(1000);
res/drawable/transition.xml
<?xml version="1.0" encoding="utf-8"?>
<transition
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/steve1"></item>
    <item android:drawable="@drawable/steve2"></item>
</transition>

En el layout, el ImageView deberá tener el siguiente atributo: android:src=”@drawable/transition”

Ejercicio

Al pulsar sobre un botón, animarlo utilizando la clase Tween, que se encargará de deformarlo.

MainActivity.java
…
Animation anim = AnimationUtils.loadAnimation(this, R.anim.animation);
Button b = findViewById(R.id.button1);
b.startAnimation(anim);

// iv.reverseTransition(1000); // hace la animación en dirección contraria
…
res/anim/animation.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:fromXScale="0.5"
        android:toXScale="2.0"
        android:fromYScale="0.5"
        android:toYScale="2.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="4000"
        >
    </scale>
</set>

Ejercicio: set de animaciones

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
	<scale xmlns:android="http://schemas.android.com/apk/res/android"
	 	android:fromXScale="0.5"
	 	android:toXScale="2.0"
	 	android:fromYScale="0.5"
	 	android:toYScale="2.0"
	 	android:pivotX="50%"
	 	android:pivotY="50%"
	 	android:duration="4000" />
	<rotate android:fromDegrees="0"
		android:toDegrees="180"
		android:pivotX="50%"
		android:pivotY="50%"
		android:duration="20000"
		android:startOffset="2000" />
</set>

Detectar el fin de una animación

El activity debe implementar la interfaz AnimationListener.

...
questionsPanel_anim.setAnimationListener(this);
questionsPanel.startAnimation(questionsPanel_anim);	
...


public void onAnimationEnd(Animation arg0) {
		if(arg0==questionsPanel_anim){
			pintarPreguntasYRespuestas();
		}
}

Animación FrameByFrame

MainActivity.java
…
ImageView iv = findViewById(R.id.imageView1);
iv.setBackgrounResource(R.drawable.animation);
AnimationDrawable animation = (AnimationDrawable) iv.getBackground();
animation.start();
res/drawable/animation.xml
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/animation_00031" android:duration="30" />
<item android:drawable="@drawable/animation_00032" android:duration="30" />
<item android:drawable="@drawable/animation_00033" android:duration="30" />
…
res/layout/activity_main.xml
<ImageView
    android:background="@drawable/animation"
    ...
/>
Descargar Recurso
← Gradle
ItemList →

Aviso Legal | Política de privacidad