Como programar en Android: Guia 2

En esta guia vamos a aprender cómo navegar entre dos Layouts (vistas) mediante la pulsación de un botón, enviando parámetros de una vista a otra.

Antes de leer esta guia, quizá te interese echar un vistazo a la anterior, donde explicábamos la estructura de una aplicación Android en Eclipse e implementábamos un sencillo Hola Mundo. Vamos a continuar con ese proyecto para completar la Guia 2.

¿Qué vamos a hacer?

Vamos a continuar con el proyecto de la Guia 1 para explicar como crear una segunda vista, que se mostrará cuando pulsemos en el botón que vamos a colocar en la primera vista. Además, enviaremos un parámetro de la primera a la segunda vista.

Paso 1 – Crear el segundo Layout

Como todas las vistas, debe estar localizada en la carpeta de recursos /res/layout, así que vamos a esa carpeta y haciendo clic derecho en ella, elegimos New/Other…/AndroidXMLFile y damos a Next. En la ventana que abre rellenamos el campo “File” dandole valor “lista.xml” y pulsamos Finish.

Como en la ventana anterior teniamos seleccionado “LinearLayout” como RootElement, nuestro Layout “lista.xml” contendrá eso como único elemento.

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

Dentro de este contendor LinearLayout, vamos a incluir un TextView donde se mostrará más adelante el parámetro enviado desde la primera vista. Queda así:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
<TextView android:id="@+id/campotexto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
</LinearLayout>

El simbolo “+” en el atributo id del TextView indica al compilador que debe agregar un nuevo recurso, de forma que luego será accesible por código así R.id.campotexto . Podemos aprender más sobre esto en la documentación.

Paso 2 – Incluir un botón en el primer Layout

Ahora que tenemos listo el segundo Layout, vamos a poner un botón en el primer Layout (recordemos que en la Guia 1 lo llamamos main.xml) que será el que abrirá la segunda vista de nuestra aplicación.

Abrimos el recurso xml res/layout/main.xml y en lugar del TextView que teníamos, vamos a poner un botón:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
 <Button android:text="Ver Lista"
        android:id="@+id/Button02"
        android:layout_width="200px"
        android:textSize="15px"
        android:layout_height="55px">
</Button>
</LinearLayout>

Paso 3 – Añadir la segunda Actividad

Recordemos que en un patrón MVC como este, cada Layout (Vista) está controlado por una Actividad.

Ya hemos diseñado el segundo Layout, ahora vamos a implementar su Actividad.

Hacemos clic derecho sobre nuestro paquete de código fuente src/com.example.tolkienlibrary y elegimos New/Class… y en la ventana que se abre le damos un nombre, en el campo “Name” con valor “ControladorLista” y pulsamos Finish.

Ahora abrimos nuestro recién creado fichero ControladorLista.java, que estará así:

package com.example.tolkienlibrary;

public class ControladorLista {

}

Como esta nueva clase debe ser una actividad, tendrá que heredar de la clase Activity. Mediante la palabra clave extends de java podemos realizar esta herencia.

Además, debemos sobreescribir el evento onCreate de la clase Actividad, que se ejecuta una vez cada vez que la Actividad se inicia, y que servirá para inicializar el estado de la Actividad y de su correspondiente Layout, que tambien debemos establecer en este método.

Ahora tendrá esta pinta:

package com.example.tolkienlibrary;

import android.app.Activity;
import android.os.Bundle;

public class ControladorLista extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.lista); //establecemos el Layout de esta Actividad
	}
}

Para añadir las referencias que faltan (los imports) en MAC OSX basta con pulsar cmd+shift+O o pasando el ratón por encima de los errores nos aparece un desplegable donde nos dicen soluciones al problema, entre ellos Importar las clases necesarias.

Paso 4 – Declarar la actividad en AndroidManifest.xml

Ya hablamos en la Guia 1 de que todas las actividades, entre otras cosas, deben ser declaradas en el fichero de Manifiesto, así pues, abrimos el AndroidManifest.xml y declaramos nuestra actividad “ControladorLista” dentro del elemento “application”. Hay que anteponer un simbolo “.” al nombre de la clase. Vemos como queda nuestro fichero.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.tolkienlibrary"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".TolkienLibrary"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
		<activity android:name=".ControladorLista"></activity>
    </application>
    <uses-sdk android:minSdkVersion="3" />
</manifest>

Paso 5 – Añadir el evento del botón

Vamos a añadir un listener que atienda el evento que provoca pulsar sobre el botón. Para ello vamos a TolkienLibrary.java y escribimos el código necesario para dejarlo así:

package com.example.tolkienlibrary;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class TolkienLibrary extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button next = (Button) findViewById(R.id.Button02);
        next.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                Intent myIntent = new Intent(view.getContext(), ControladorLista.class);
                startActivityForResult(myIntent, 0);
            }
        });
    }
}

Veamos que estamos haciendo:

  • Buscamos el botón cuyo id es Button02 dentro de los recursos de nuestro Layout (es el ID que le dimos en main.xml).
  • Una vez obtenido el objeto botón, le asignamos un listener para el evento OnClick
  • Dentro del Listener vamos a ejecutar un método que creará un objeto Intent sobre la actividad ControladorLista
  • Finalmente con startActivityForResult(myIntent, 0) ejecutamos la Actividad, y esperamos que esta nos devuelva un resultado.

A estas alturas nos estaremos preguntando que es eso de “Intent”. Intent es un objeto que recopila información de interés para el sistema Android y que a efectos prácticos nos permite solicitar que se ejecute una Actividad. Como siempre, aqui esta la documentación.

Paso 6 – Enviar parámetros a la segunda vista

Habíamos quedado en que ibamos a enviar algún parametro a la segunda vista. Para eso, en el evento del botón del nuestra actividad TolkienLibrary, vamos a construir un Bundle y a pasarselo a la vista, un Bundle no es más que una colección de claves/valor que la vista recibe cuando el sistema la restaura.

package com.example.tolkienlibrary;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class TolkienLibrary extends Activity {

	final public static String MyKey = "mikey";

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		Button next = (Button) findViewById(R.id.Button02);
		next.setOnClickListener(new View.OnClickListener() {
			public void onClick(View view) {

				// Cargamos el Bundle con la coleccion de objetos que pasaremos
				// a la siguiente vista
				Bundle bundle = new Bundle();
				bundle.putString(MyKey,
						"Esto lo hemos enviado desde la vista principal.");

				// Creamos la vista de Lista de objetos y le pasamos la
				// colección de objetos a mostrar
				Intent myIntent = new Intent(view.getContext(),
						ControladorLista.class);
				myIntent.putExtras(bundle);

				startActivityForResult(myIntent, 0);
			}

		});
	}
}

Prestad atención a MyKey, que funciona como clave del parametro que estamos enviando en nuestro Bundle.

Paso 7 – Recibir el parámetro

Como quien va a recibir el parámetro es nuestra Actividad ControladorLista abrimos el fichero ControladorLista.java y escribimos lo siguiente:

package com.example.tolkienlibrary;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class ControladorLista extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.lista); //establecemos el Layout de esta Actividad

		Bundle extras = getIntent().getExtras();
        if (extras != null) {
            String parametro = extras.getString(TolkienLibrary.MyKey);

            //utilizamos el parametro
            TextView controlTexto = (TextView) findViewById(R.id.campotexto);
            controlTexto.setText(parametro);
        }
	}
}

Una explicación al respecto:

Obtenemos desde el objeto Intent los Extras, mediante .getExtras().

Si hemos recibido alguno, entonces obtenemos el String que introducimos en la vista principal en la colección, mediante la clave MyKey.

Por ultimo buscamos en el Layout de la segunda vista el TextView cuyo id es “campotexto” y establecemos su texto al parametro que hemos recibido.

Paso 8 – Responder a la vista principal

Ahora, como paso opcional, vamos a aprender a responder a la Actividad que nos llamó. Para ello vamos a incluir en el segundo Layout (lista.xml) y vamos a añadir otro botón.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
	android:layout_width="fill_parent" android:layout_height="fill_parent">
	<TextView android:id="@+id/campotexto"
		xmlns:android="http://schemas.android.com/apk/res/android"
		android:layout_width="wrap_content" android:layout_height="wrap_content" />
	<Button android:text="Volver" android:id="@+id/ButtonVolver"
		android:layout_width="200px" android:textSize="15px"
		android:layout_height="55px">
	</Button>
</LinearLayout>

Despues, como siempre, añadimos en la Actividad de este Layout el Listener que maneja el evento clic del botón:

package com.example.tolkienlibrary;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class ControladorLista extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.lista); //establecemos el Layout de esta Actividad

		Bundle extras = getIntent().getExtras();
        if (extras != null) {
            String parametro = extras.getString(TolkienLibrary.MyKey);

            //utilizamos el parametro
            TextView controlTexto = (TextView) findViewById(R.id.campotexto);
            controlTexto.setText(parametro);
        }

        Button next = (Button) findViewById(R.id.ButtonVolver);
		next.setOnClickListener(new View.OnClickListener() {
			public void onClick(View view) {
				 Bundle bundle = new Bundle();
			        bundle.putString(TolkienLibrary.MyKey, "Este valor lo hemos enviado desde la segunda vista.");
			        Intent mIntent = new Intent();
			        mIntent.putExtras(bundle);
			        setResult(RESULT_OK, mIntent);
			        finish();
			}

		});
	}
}

Vamos a ver que hemos hecho:

  • Hemos creado un Listener para el evento Clic del botón “ButtonVolver”
  • En botón, creamos un Bundle, y usando por ejemplo la misma clave de antes “MyKey”, almacenamos un par clave/valor.
  • Creamos un objetos Intent y le agregamos como Extras nuestro objeto Bundle cargado de información.
  • Mediante el método setResult, establecemos el resultado de esta actividad (recordemos que cuando invocamos a esta Actividad desde la Actividad principal, lo hicimos mediante la llamada startActivityForResult que espera un resultado por parte de la Actividad invocada) y entregamos el objeto Intent.
  • Llamamos a finish para forzar el fin de la Actividad actual.

De esta forma, estaríamos entregando también información de retorno a la Actividad TolkienLibrary al pulsar el botón.

Podemos ejecutar al fin, y veremos un botón, haciendo click sobre el se muestra el segundo Layout, y el texto es el parametro que enviamos desde la primera Actividad:

Segundo Layout

Paso 9 – Futuras Guías…

Guia 1 – Hola Mundo en Android.

Guia 2 – Navegación entre Layouts con un botón, y paso de parámetros.

Guia 3 – ListView o listas con scroll.

Guia 4 – ListView ricas con celdas personalizadas e imágenes.

Guia 5 – Acceso a base de datos (SQLLite).

12 Comments / Add your own comment below

  1. Me tira error en
    Button next = (Button) findViewById(R.id.Button02);

    dice q no encuentra button02… por q no esta declarado en ninguna parte.. por lo q vi, solo esta declarado button1 en la guia…

  2. Muchas gracias Andres por el aviso.

    Efectivamente, como dices, hay un error en el código del Paso 2. El error que lanzaba se debía a que no existía el recurso en el Layout.

    Ya esta corregido, ahora en el Layout el Botón se llama Button02 para que sea coherente con el resto de Guías.

    Un saludo y nuevamente muchas gracias!

  3. Hola!, gracias por tu guía, me ha sido muy útil para entender la navegación entre vistas.

    Tengo una duda en la que espero me puedas ayudar a solucionar; la parte que explicas al finalizar de como responder desde la segunda vista hacia la principal no me ha funcionado.

    Ya he agregado la forma con la que explicas para leer el parámetro en el activity principal. Debo hacer algun refresh o algo similar en mi activity principal? para que tome el cambio y muestre el parámetro que dice: “Este valor lo hemos enviado desde la segunda vista.”

    Gracias

  4. Hola Dani,
    Tu pregunta tiene mucho sentido, y es que la carga del texto “Este valor lo hemos enviado desde la segunda vista” no está explicado en el manual, porque sería idéntico al Paso 7.
    En el Paso 8 se está explicando como enviar el parametro a la vista principal, pero faltaría (en esa vista principal) recibir el parámetro con extras.getString(TolkienLibrary.MyKey) igual que se está haciendo en el Paso 7, y escribirlo en el TextView.

    Siento haberte generado esa confusión, pero el Paso 8 es solo un ejemplo de como se devolveria información desde una vista, aunque no estaba implementada la recepcion.

    Un saludo!

  5. Pingback: Como programar en Android: Guia 3

  6. Muchas gracias, justo lo que necesitaba…
    excelentes guias ^^

  7. Buenas, a la hora de programación no tengo ningún problema, pero al ejecutar mi aplicación y al darle en el bottom me aparece un error que dice :

    The application NombreApp (process gonzalo.NombreApp) has stopped unexpectedly. Please try again.

    Si sabes como solucionarlo me vendría muy bien, Gracias por tu tiempo.

  8. Pingback: Como programar en Android: Guia 1

  9. Pingback: Como programar en Android: Guia 4

  10. Enhorabuena
    Muy útil y directa la guia.
    Y muy bien explicado. Gracias por el aporte

  11. gon250 estás colocando la programación fuera del OnCreate, o en algún lugar no debido.
    Por ejemplo, ese error suele ocurrir, al meter las funciones del onclick dentro de la clase, pero fuera del OnCreate.

    Saludos.

  12. Hola, no he logrado mostrar en la vista principal, el texto que enviamos desde la segunda vista.

    Me puedes mostrar como queda el codigo final de la vista principal para que se muestre el segundo texto?

    Saludos.

Leave a Reply

Your email address will not be published. Required fields are marked *