Ejercicio 2
Aprenderemos a:
- Crear una actividad y añadirla al fichero
AndroidManifest.xml
- Invocar otra actividad asíncronamente mediante el método
startActivityForResult()
- Pasar datos entre actividades en objetos Bundle
- Utilizar layouts más avanzados
- Crear un menú contextual
Paso 1
Echa una ojeada al proyecto.
Paso 2
Abre la clase Notepadv2.
1. Para que cada elemento de la lista del ListView aparezca en el menú contextual llamamos a
registerForContextMenu()
y le pasamos nuestro ListView. Por tanto, al final del método onCreate()
añade la siguiente línea:registerForContextMenu(getListView());
getListView()
devolverá el objeto ListView local de la actividad. Añadiendo esta línea cada elemento de la lista de este ListView activará el menú contextual.onCreateContextMenu().
Añade la siguiente línea, que añadirá el elemento de menú para eliminar una nota:A la llamada onCreateContextMenu() se le pasa, además del objeto Menu, la vista que se ha activado para el menú e información extra del objeto seleccionado. Sin embargo, no nos importa mucho ya que sólo tenemos un tipo de objeto en la actividad que use menús contextuales. En el próximo paso gestionaremos la selección de elementos del menú.
Paso 3
onContextItemSelected()
con el siguiente código (clic para ampliar, se puede copiar del paso 3 de esta página):Paso 4
Crea un objeto Intent para crear una nota (ACTIVITY_CREATE) mediante la clase NoteEdit. Entonces activa el Intent mediante el método startActivityForResult():
Intent i = new Intent(this, NoteEdit.class);
startActivityForResult(i, ACTIVITY_CREATE);
Paso 5
Se trata de un método invocado cuando el usuario selecciona un elemento de la lista, al que se le pasan cuatro parámetros: el objeto ListView desde el que se invoca, la View dentro de la ListView en la que se hizo clic, y el mRowId del elemento clicado. En nuestro caso podemos ignorar los dos primeros (sólo tenemos una ListView) y el mRowId. Lo que nos interesa es la posición (position) que el usuario ha seleccionado. Lo utilizamos para obtener los datos de la fila correcta.
Intent
para editar la nota mediante la clase NoteEdit
. Luego añade información extra que se pasará a la actividad invocada: título, texto y el mRowId
de la nota que editemos. Finalmente, lanza el Intent mediante una llamada al método startActivityForResult()
. Éste es el código de onListItemClick()
:super.onListItemClick(l, v, position, id);
Cursor c = mNotesCursor;
c.moveToPosition(position);
Intent i = new Intent(this, NoteEdit.class);
i.putExtra(NotesDbAdapter.KEY_ROWID, id);
i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
startActivityForResult(i, ACTIVITY_EDIT);
Paso 6
onActivityResult()
es el método que se llamará cuando una Activity devuelva un resultado (una Activity devolverá un resultado sólo si es lanzada usando startActivityForResult
.). Los parámetros pasados son los siguientes:requestCode
— puede serACTIVITY_CREATE
oACTIVITY_EDIT
en nuestro caso.resultCode
— el resultado (o código de error) de la llamada, puede ser 0 si todo fue correcto, o diferente de 0 si algo falló. Hay códigos de resultado estándar disponibles, incluso nos podemos crear nuestras constantes para indicar los diferentes tipos de error.intent
— Intent creado por los resultados devueltos. Se puede usar para devolver datos en los "extras." del Intent.
La combinación de startActivityForResult()
y onActivityResult()
se puede tomar como una RPC (remote procedure call) asíncrona y es la manera recomendada de una actividad para invocar y compartir servicios con otra.
Éste es el código del método (clic para ampliar, se puede copiar del paso 6 de esta página):
Paso 7
res/layout/note_edit.xml
y échale una ojeada. Es el código de la interfaz de usuario del Editor de Notas.Esta vez se trata de una interfaz sofisticada, por lo que se proporciona el fichero ya creado.
Se utiliza un nuevo parámetro que no hemos visto antes:
android:layout_weight
layout_weight
se utiliza en LinearLayouts para asignar "importancia" a las diferentes Views del layout. Todas las Views tienen un layout_weight
por defecto con valor 0, lo que significa que sólo toman el espacio justo que necesitan en pantalla para ser visibles. Si asignamos un valor superior la pantalla dividirá el resto del espacio disponible de la View padre, de acuerdo al valor layout_weight
de cada View y su proporción respecto al layout_weight
general especificado.
Por ejemplo: supongamos que tenemos una etiqueta de texto y dos elementos de edición de texto en una fila horizontal. la etiqueta no tiene ningún layout_weight
especificado, por lo que toma el espacio mínimo para ser mostrada. Si asignamos el valor 1 al layout_weight
de cada uno de los dos elementos de edición de texto, el ancho restante del layout padre será dividido en partes iguales entre ellos (porque consideramos que son igual de importantes). Si el primero tuviera un layout_weight
de 1 y el segundo de 2, un tercio del espacio sobrante sería asignado al primero, y dos tercios al segundo (porque estamos diciendo que es más importante).
Este layout también demuestra como anidar múltiples layouts uno dentro del otro para conseguir un layout más complejo. En este caso tenemos un linear layout horizontal dentro de otro vertical para que la etiqueta de título y el texto estén una al lado del otro horizontalmente.
Paso 8
Es la primera vez que creamos una actividad sin que el plugin de Eclipse lo haga por nosotros. Cuando lo hagas, verás que el método
onCreate()
no es generado automáticamente. Tendrás que hacerlo tú:- Haz clic derecho en el paquete
com.android.demo.notepad2
y selecciona New > Class - Escribe
NoteEdit
en el campName:
- En el campo
Superclass:
escribeandroid.app.Activity
- Haz clic en Finish.
- En la clase
NoteEdit
creada, haz clic derecho y selecciona Source > Override/Implement Methods... - Desplázate hacia abajo a través de la lista hasta que veas
onCreate(Bundle)
y selecciónalo. - Haz clic en OK.
Ahora el método debería aparecer.
Paso 9
onCreate()
de NoteEdit
. Esto establecerá el título de la actividad a "Editar nota", uno de los strings definidos en strings.xml. Si quieres puedes traducirlo como yo)
:
También establecerá el uso del fichero de layout note_edit.xml
.
- Dentro de
onCreate()
, establece el layout:setContentView(R.layout.note_edit);
- Cambia el título de la Activity por el de "Editar Nota"
setTitle(R.string.edit_note);
- Encuentra los componentes EditText y Button necesarios. Se encuentran por los IDs asociados a ellos en la clase R:
mTitleText = (EditText) findViewById(R.id.title);
mBodyText = (EditText) findViewById(R.id.body);
Button confirmButton = (Button) findViewById(R.id.confirm);Recuerda declarar los atributos
mTitleText
andmBodyText.
- En la parte superior de la clase declara un atributo privado
Long mRowId
para guardar elmRowId
que se esté editando (si se está editando alguno). - Continuando con
onCreate()
, añade el siguiente código para inicializartitle
,body
ymRowId
de los Bundle extra del Intent (si está presente):mRowId = null;
Bundle extras = getIntent().getExtras();
if (extras != null) {
String title = extras.getString(NotesDbAdapter.KEY_TITLE);
String body = extras.getString(NotesDbAdapter.KEY_BODY);
mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
if (title != null) {
mTitleText.setText(title);
}
if (body != null) {
mBodyText.setText(body);
}
} - Crea un
onClickListener()
para el botón:Queremos que se llame a un método
onClick()
cuando el usuario presione el botón de confirmación, y utilizarlo para hacer algo y devolver los valores de la nota editada al invocador del Intent. Añade el siguiente listener vacío al método onCreate():confirmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
}
});
Paso 10
onClick()
del OnClickListener.
Este es el código que se ejecutará cuando el usuario haga clic en el botón de confirmación:
- Crea un
Bundle
y ponle título y texto utilizando las constantes definidas en Notepadv2:Bundle bundle = new Bundle();
bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
if (mRowId != null) {
bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
} - Pasa el resultado (el Bundle) a un nuevo Intent y finaliza la actividad:
Intent mIntent = new Intent();
mIntent.putExtras(bundle);
setResult(RESULT_OK, mIntent);
finish();
El código completo de la clase NoteEdit debería tener el siguiente aspecto (clic para ampliar, se puede copiar del paso 10 de esta página):
Paso 11
AndroidManifest.xml
.Para que una Android vea una actividad es necesario que ésta tenga una entrada en
AndroidManifest.xml
. El plugin de Eclipse incluye un editor de Manifest que facilita mucho la edición del archivo, y será el que utilizaremos:
- Abre el fichero
AndroidManifest.xml
- Selecciona la pestaña Application en el editor de Manifest editor
- Haz clic en Add... en la sección Application Nodes
- Asegúrate de que está seleccionado "(A) Activity" en el panel de selección del diálogo y haz clic en OK.
- Haz clic en el nuevo nodo "Activity" en la sección "Application Nodes", y escribe
.NoteEdit
en el campo Name* de la derecha. Presiona Enter
Paso 12
Ahora deberías poder añadir notas desde el menú, así como eliminar una existente. Fíjate que para eliminar, primero tienes que utilizar los controles direccionales del aparato para resaltar la nota y luego hacer un clic largo en ella. Además, el hecho de seleccionar una nota desde la lista debería hacer aparecer el editor de notas para editarla. Confirma cuando hayas acabado de editar la nota para guardar los cambios en la base de datos.
Solución
En el ejercicio 3 corregiremos acabaremos de pulir la aplicación añadiendo un ciclo de vida correcto que solucionará algunos errores.
7 comentarios:
Gracias por los tutoriales, me han sido de mucha ayuda... Pero en especial con este tengo un problema, no me está generando la clase R.java automáticamente y no se como solucionarlo, si puedes ayudarme lo agradecería
Hola Belmar
De nada.
La clase R se debe generar automáticamente.
Si no lo hace, algo está mal configurado.
Comprueba que la opción "Project->Build automatically" está habilitada. Luego prueba a modificar un fichero xml (por ejemplo AndroidManifest.xml) y dejarlo como estaba para forzar a eclipse a reconstruir la clase R.
Puedes acompañarlo de un reinicio de Eclipse.
Hola probe lo que dijiste pero en realidad debe ser algo con la forma de realizar el código, porque para el ejemplo uno si funciona perfecto, de todas manera lo hice manual y aqui les dejo link de descarga http://www.megaupload.com/?d=G7YYWL31 del ejemplo base lo extraen y lo pegan en el workspace y simplemente le dan a importar proyecto existente en el espacio de trabajo y ya. Gracias por los tutoriales estan muy buenos.
Gracias a ti por tu colaboración :)
Para hacer el onActivityResult() este debe hacerse en otra activity diferente a la del startActivityforResult(), tengo esa duda gracias
Fíjate en el proyecto Notepadv2Solution:
https://github.com/hone/NotepadCodeLab/tree/43aa0d725cb18a412e677d45e5cd46e1cc70ced8/Notepadv2Solution/src/com/android/demo/notepad2
Publicar un comentario