En este ejercicio agregaremos una segunda "Activity" a nuestra aplicación de anotaciones y permitiremos que el usuario cree, edite y borre anotaciones. La nueva "Activity" asumirá la responsabilidad de crear nuevas anotaciones al colectar los datos de entrada del usuario y empaquetarlos y devolverlos a la "Activity" que la invocó.
Este ejercicio demostrará:
- Desarrollo de una nueva "Activity" y cómo agregarla al archivo "Android manifest".
- Invocación asincrónica de otra "Activity" usando "startSubActivity()".
- Paso de datos entre "Activity" ("bundles").
- Cómo utilizar características más avanzadas de diseño de pantalla.
Importa el proyecto "Notepadv2" de la misma forma en que lo describí en el tutoríal anterior. Los archivos de este proyecto están localizados en el directorio "NotepadCodeLab". Si se te presenta un error con el archivo "AndroidManifest.xml" o con el archivo "android.zip", abre el menú de contexto del proyecto y selecciona la opción "Android Tools->Fix Project Properties".
Expande el proyecto "Notepadv2" y dale un vistazo general:
- Abre y examina el archivo "strings.xml" (directorio "res/values"). Verás la declaración de nuevas cadenas de texto, las cuales las usaremos en las nuevas funcionalidades.
- Abre y examina el encabezado de la clase "Notepadv2". Notarás que también hay algunos cambios: declaraciones de nuevas constantes y propiedades.
- También notarás que el método "fillData()" ha sido modificado para usar la propiedad "rows" en vez de una variable local.
- Adicionalmente, hemos sobreescrito nuevos métodos: "onListItemClick()" y "onActivityResult()".
Revisa el método "onCreate()", verás que no ha cambiado desde la versión anterior.
Paso #3
Debemos agregar la opción "Delete Note" al menú de la "Activity". Para esto:
- En el método "onCreateOptionsMenu()" agrega la siguiente línea:
menu.add(0, DELETE_ID, R.string.menu_delete); |
- Ahora, el método debería verse así:
@Override |
Paso 4
- En el método "onMenuItemSelected()" agrega el siguiente fragmento de código:
case DELETE_ID: |
Este código usa el método "getSelection()" perteneciente a "ListActivity", el cual nos indica cual es el actual elemento seleccionado de la lista. Luego, referenciamos el registro de esa anotación y finalmente tomamos el valor de la propiedad "rowId". Es este valor el que finalmente utilizamos con "deleteRow" para borrar el registro.
- Posteriormente, llamamos al método "fillData()" para mantener todo actualizado.
- El método debería quedar de la siguiente forma:
@Override |
Paso 5
Ahora, modificaremos el cuerpo del método "createNote()":
- Definiremos un "Intent" para crear una anotación ("ACTIVITY_CREATE"). Los argumentos que utilizaremos será "this" y la clase "NoteEdit". A continuación, gatillaremos el "Intent" usando el método "startSubActivity()".
NOTA: En este ejemplo, nuestro "Intent" utiliza el nombre específico de una clase. Mientras esto es adecuado para determinadas circunstancias, lo más común es invocar un "Intent" usando una "Action" y una "URI". Ver "android.content.Intent" para más información.
Paso 6
Modificaremos el cuerpo del método "onListItemClick()".
El método "onListItemClick()" sobreescribe el método que es llamado cuando un usuario selecciona un elemento de la lista. Este método entrega 4 parámetros:
- Objeto ListView : referencia al objeto desde el cual fue invocado el elemento.
- Objeto View : referencia al objeto que fue seleccionado dentro de la ListView.
- Un entero con la posición del elemento seleccionado.
- Un entero con la identificación del elemento que fue seleccionado.
Este método crea el "Intent" para editar la anotación usando la clase "NoteEdit". Luego, agregamos todos los datos al "Intent" (título, cuerpo de la anotación y la identificación). Finalmente, gatillamos el "Intent" invocando al método "startSubActivity()" con los argumentos "ACTIVITY_EDIT" y la clase "NoteEdit".
super.onListItemClick(l, v, position, id); |
Paso 7
A continuación modificaremos el método "onActivityResult()".
El método "onActivityResult()" sobreescribe un método que es invocado cuando una sub "Activity" finaliza su tarea. Los parámetros que este método entrega son:
- requestCode : s el código original utilizado en la invocación del "Intent" (en nuestro caso podrá ser "ACTIVITY_CREATE" o "ACTIVITY_EDIT").
- resultCode : es el resultado (o código de error) del llamado. Este valor debería ser cero si todo fue correcto y valor distinto para indicar que algo falló. Existen algunos códigos predefinidos que pueden ser utilzados, pero también pueden definirse nuevos códigos para errores más específicos.
- data : esta es una cadena de texto que es utilizada para recibir algún tipo de información descriptiva (por ejemplo: el texto que el usuario escribió en un cuadro de diálogo). Esto es útil únicamente cuando tenemos sólo una cosa que devolver. Si requerimos retornar más información, debemos usar "extras".
- extras : este parámetro entrega los "extras bundle" (si es que existen) que retornó el "Intent" invocado.
A continuación está el código completo de este método:
@Override |
- En este método distinguimos los resultados de dos "Activity": "ACTIVITY_CREATE" y "ACTIVITY_EDIT".
- En el caso de "ACTIVITY_CREATE", tomamos el título y el cuerpo desde "extras" para usarlos en la creación de la anotación.
- En el caso de "ACTIVITY_EDIT", tomamos además el "KEY_ROW_ID" para localizar el registro que deseamos actualizar.
- El método "fillData()" al final nos asegura que todo será actualizado.
Abre el archivo "note_edit.xml" y revísalo. Este archivo contiene la definición de la pantalla que será usada para editar nuestras anotaciones.
Este archivo hace uso de un nuevo parámetro: "android:layout_weight" (en este caso tiene el valor "1").
layout_weight es usado en "LinearLayouts" para asignar a las vistas un nivel de "importancia" dentro del diseño de la pantalla. Todas las vistas tienen un valor por omisión de cero para "layout_weight", lo cual significa que ellas pueden ocupar el espacio que requieran para ser desplegadas. Al asignar un valor mayor que cero hará que el resto del espacio disponible sea dividido entre el padre de acuerdo al valor de "layout_weight" y su proporción con el total de "layout_weight", especificado en el actual trazado y en otras vistas.
Para dar un ejemplo de lo anterior, digamos que tenemos una etiqueta de texto y dos áreas de edición en un vista horizontal. La etiqueta de texto no tiene especificado valor para su "layout_weight", por lo tanto tomará el mínimo espacio requerido para desplegarse. Si el valor de "layout_weight" para las áreas de texto es "1", el restanto espacio dentro del área definida por el padre será dividida entre ambas. Si la primera área tuviera un valor de "1" y la segunda un valor de "2" para "layout_weight", entonces un tercio del espacio disponible será entregado a la primera área y los dos restantes a la segunda.
Este diseño de pantalla también demuestra cómo anidar múltiples esquemas para así lograr complejos trazados de pantalla. En este caso, el esquema horizontal lineal está anidado dentro de uno vertical, lo cual permite que la etiqueta del título y el área de edición estén una al lado de otra.
Paso 9
Crea una clase llamada "NoteEdit" y que extienda "android.app.Activity".
Esta es la primera vez que crearemos una "Activity" sin la ayuda del "Android Eclipse plugin". Al hacerlo de esta manera, el método "onCreate()" no es automáticamente etiquetado con la anotación de sobreescritura. Es difícil imaginar una "Activity" que no sobreescriva el método "onCreate()".
A continuación están las instrucciones en detalle:
- Abre el menú de contexto del paquete "com.google.android.demo.notepad2" y selecciona "New->Class".
- Escribe en el campo "Name:" el nombre de la clase ("NoteEdit").
- En el campo "Superclass:", escribe "android.app.Activity" o puedes simplemente escribir "Activity" y presionar "Ctrl-Space" (Windows y Linux) para invocar el asistente de código y encontrar path completo del paquete en el cual está esta clase.
- Presiona el botón "Finish".
- En el editor de texto abre el menú de contexto y selecciona la opción "Source", luego selecciona "Override/Implement Methods...".
- Busca el método "onCreate(Bundle)" y selecciónalo.
- Presiona el botón "OK".
Completaremos el código del método "onCreate()".
Haremos las declaraciones necesarias para definir el título de nuestra "Activity" ("Edit Note"). Este valor está definido en el archivo "strings.xml". Aquí también definiremos que la vista que utilizaremos será aquella definida en el archivo "note_edit.xml layout". Después de esto, podemos asociar a objetos Java las vistas correspondientes al título, el cuerpo de la anotación y el botón de confirmación. De esta forma, nuestro código puede usarlos para asignar y recuperar el texto del título y el cuerpo; y además asociar cñodigo al evento gatillado cuando el usuario presiona el botón de confirmación.
Los valores que fueron enviados por la "Notepadv2" serán extraidos desde el paquete y usados para llenar el título y el cuerpo de la anotación. La identificación de la anotación la almacenaremos para saber que registro estamos editando.
- Asociación de la "Activity" con un esquema:
- Examinar el esquema de pantalla para encontrar el título, el cuerpo y el botón de confirmació. Utilizamos los identificadores generados en la clase "R" y luego los convertimos al tipo apropiado.
bodyText = (EditText) findViewById(R.id.body);
Button confirmButton = (Button) findViewById(R.id.confirm);
NOTA: "titleText" y "bodyText" son propiedades de la clase que aún no hemos definido.
- Declarar una propiedad llamada "rowId", la cual almacenará la identificación del registro editado.
- Agregar código para inicializar el título, cuerpo y la propiedad "rowId" a partir de los datos extraidos del paquete recibido desde "Notepadv2".
Bundle extras = getIntent().getExtras();
if (extras != null) {
String title = extras.getString(Notepadv2.KEY_TITLE);
String body = extras.getString(Notepadv2.KEY_BODY);
rowId = extras.getLong(Notepadv2.KEY_ROW_ID);
if (title != null) {
titleText.setText(title);
}
if (body != null) {
bodyText.setText(body);
}
}
- Definir un controlador para el evento clic del botón de confirmación. Esto lo hacemos utilizando el método "onClickListener()".
Paso 11
Completaremos el cuerpo del método "onClick()".
Este es el código que se ejecutará cuando el usuario haga clic sobre el botón de confirmación. Aquí es donde debemos recuperar el título y cuerpo de la anotación y colocarlos dentro del paquete de datos que devolveremos a la "Activity" que invocó esta "Activity". Si la operación es editar en vez de crear, también deberemos poner la identificación del registro de la anotación.
- Creación del paquete donde pondremos el título y cuerpo de la anotación.
bundle.putString(Notepadv2.KEY_TITLE, titleText.getText().toString());
bundle.putString(Notepadv2.KEY_BODY, bodyText.getText().toString());
if (rowId != null) {
bundle.putLong(Notepadv2.KEY_ROW_ID, rowId);
}
- Asignar la información de resultado, incluyendo el paquete y resultado final de la operación.
finish();
El método "setResult()" es usado para asignar el código de retorno, la cadena de información textual y el paqueta de datos que será entregado al "Intent" que invocó a esta "Activity". En este caso suponemos que todo estará bien, asi es que devolvemos "RESULT_OK" como valor del código de retorno. No usaremos la cadena de información textual , por esta razón estamos pasando el valor "null".
El método "finish()" es usado como una señal que la "Activity" ha realizado su tarea (una especia de "return"). Todos los argumentos entregados a "setResul()" van a ser devueltos junto con el control de ejecución.
- La siguiente es la declaración de las propiedades utilizadas en el código de esta clase.
private EditText bodyText;
private Long rowId;
- El código completo del método "onCreate()" es mostrado a continuación.
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.note_edit);
titleText = (EditText) findViewById(R.id.title);
bodyText = (EditText) findViewById(R.id.body);
Button confirmButton = (Button) findViewById(R.id.confirm);
rowId = null;
Bundle extras = getIntent().getExtras();
if (extras != null) {
String title = extras.getString(Notepadv2.KEY_TITLE);
String body = extras.getString(Notepadv2.KEY_BODY);
rowId = extras.getLong(Notepadv2.KEY_ROW_ID);
if (title != null) {
titleText.setText(title);
}
if (body != null) {
bodyText.setText(body);
}
}
confirmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putString(Notepadv2.KEY_TITLE, titleText.getText().toString());
bundle.putString(Notepadv2.KEY_BODY, bodyText.getText().toString());
if (rowId != null) {
bundle.putLong(Notepadv2.KEY_ROW_ID, rowId);
}
setResult(RESULT_OK, null, bundle);
finish();
}
});
}
Paso 12
Finalmente, la nueva "Activity" debe ser declarada en el archivo "Android Manifest".
Antes de que una actividad pueda ser "vista" por Android, esta actividad debe tener su propia entrada en el archivo"AndroidManifest.xml". Esto le entregará al sistema la información necesaria para localizar la actividad y saber que requiere para funcionar.
A continuación se muestra el archivo "AndroidManifest.xml" modificado:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.demo.notepad2">
<application android:icon="@drawable/icon">
<activity class=".Notepadv2" android:label="@string/app_name">
<intent-filter>
<action android:value="android.intent.action.MAIN" />
<category android:value="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity class=".NoteEdit"/>
</application>
</manifest>
Paso 13
Ejecución de la aplicación.
1. Haz clic con el botón derecho sobre el proyecto "Notepadv2" para abrir el menú de contexto y seleccionar "Run As > Android Application".
No hay comentarios.:
Publicar un comentario