Como sabemos cada vez que iniciamos una aplicaciĆ³n que utiliza un ListView debemos cargar sus elementos. En el concepto anterior vimos que podemos agregar elementos en forma dinĆ”mica. Ahora veremos como almacenan los datos mediante la clase SharedPreferences (vimos en un concepto anterior que esta clase nos facilita guardar datos en un archivo XML mediante una clave,valor)
En el momento que inicia la aplicaciĆ³n procederemos a leer el contenido del archivo de preferencias y a aƱadir los datos al ListView. Durante la ejecuciĆ³n del programa cuando se agreguen o eliminen elementos del ListView tambiĆ©n procederemos a hacerlo del archivo de preferencias.
Problema:
Confeccionaremos una aplicaciĆ³n similar al concepto anterior que muestre un ListView con nĆŗmeros telefĆ³nicos y sus titulares, que permita agregar y eliminar nĆŗmeros durante la ejecuciĆ³n del programa. Le agregaremos lo necesario para que los datos reflejados en el ListView se almacenen en un archivo de preferencias para evitar que se borren cuando se finaliza la aplicaciĆ³n.
Cada vez que arranque el programa procederemos a leer el archivo de preferencias y poblaremos el ListView.
Crear un proyecto llamado "Proyecto054".
La interfaz visual de la aplicaciĆ³n cuando la ejecutemos serĆ” parecida a esta:

El archivo XML 'activity_main.xml' es:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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" tools:context=".MainActivity"> <EditText android:id="@+id/et1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:ems="10" android:hint="nombre" android:inputType="textPersonName" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/et2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:ems="10" android:hint="telefono" android:inputType="textPersonName" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/et1" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="13dp" android:layout_marginLeft="13dp" android:layout_marginTop="13dp" android:onClick="agregar" android:text="Agregar" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/et2" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:text="presiĆ³n larga sobre el telefono a borrar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.502" app:layout_constraintStart_toEndOf="@+id/button" app:layout_constraintTop_toBottomOf="@+id/et2" /> <ListView android:id="@+id/list1" android:layout_width="394dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button" /> </androidx.constraintlayout.widget.ConstraintLayout>
Hemos iniciado la propiedad onClick con el nombre del mƩtodo a ejecutar al ser presionado:
android:onClick="agregar" />
Por otro lado hemos fijado con "true" la propiedad focusableInTouchMode del RelativeLayout para que no aparezca con foco el primer EditText:
android:focusableInTouchMode="true">
Ahora pasemos al archivo MainActivity.java
package com.tutorialesprogramacionya.proyecto054; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ListView; import java.util.ArrayList; import java.util.Map; import java.util.StringTokenizer; public class MainActivity extends AppCompatActivity { private ArrayList<String> datos; private ArrayAdapter<String> adaptador1; private ListView lv1; private EditText et1,et2; private SharedPreferences prefe1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); datos =new ArrayList<String>(); leerSharedPreferences(); adaptador1=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, datos); lv1=(ListView)findViewById(R.id.list1); lv1.setAdapter(adaptador1); et1=(EditText)findViewById(R.id.et1); et2=(EditText)findViewById(R.id.et2); lv1.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) { final int posicion=i; AlertDialog.Builder dialogo1 = new AlertDialog.Builder(MainActivity.this); dialogo1.setTitle("Importante"); dialogo1.setMessage("Āæ Elimina este telĆ©fono ?"); dialogo1.setCancelable(false); dialogo1.setPositiveButton("Confirmar", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogo1, int id) { String s=datos.get(posicion); StringTokenizer tok1=new StringTokenizer(s,":"); String nom=tok1.nextToken().trim(); SharedPreferences.Editor elemento=prefe1.edit(); elemento.remove(nom); elemento.commit(); datos.remove(posicion); adaptador1.notifyDataSetChanged(); } }); dialogo1.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogo1, int id) { } }); dialogo1.show(); return false; } }); } private void leerSharedPreferences() { prefe1=getSharedPreferences("datostelefonos", Context.MODE_PRIVATE); Map<String,?> claves = prefe1.getAll(); for(Map.Entry<String,?> ele : claves.entrySet()){ datos.add(ele.getKey()+" : " +ele.getValue().toString()); } } public void agregar(View v) { datos.add(et1.getText().toString()+" : "+et2.getText().toString()); adaptador1.notifyDataSetChanged(); SharedPreferences.Editor elemento=prefe1.edit(); elemento.putString(et1.getText().toString(),et2.getText().toString()); elemento.commit(); et1.setText(""); et2.setText(""); } }
Definimos como atributos el ArrayList que almacena en memoria la lista de telĆ©fonos y titulares llamado datos, el ArrayAdapter que cumple como funciĆ³n ser el puente entre el ArrayList y el ListView, el ListView que muestra los datos, los dos EditText y finalmente la variable prefe1 de la clase SharedPreferences que nos permite almacenar en forma permanente los datos y su posterior recuperaciĆ³n:
private ArrayList<String> datos; private ArrayAdapter<String> adaptador1; private ListView lv1; private EditText et1,et2; private SharedPreferences prefe1;
En el mƩtodo onCreate creamos el ArrayList:
datos =new ArrayList<String>();
Procedemos a llamar al mƩtodo leerSharedPreferences() que tiene por objetivo leer el archivo de preferencias que almacena todos las personas y sus telƩfonos.
El mƩtodo de lectura es:
private void leerSharedPreferences() { prefe1=getSharedPreferences("datostelefonos", Context.MODE_PRIVATE); Map<String,?> claves = prefe1.getAll(); for(Map.Entry<String,?> ele : claves.entrySet()){ datos.add(ele.getKey()+" : " +ele.getValue().toString()); } }
Llamamos al mƩtodo getSharedPreferences pasando el nombre del archivo de preferencias y el modo de apertura:
prefe1=getSharedPreferences("datostelefonos", Context.MODE_PRIVATE);
Creamos un objeto de la clase Map llamando al mƩtodo getAll del SharedPreferences:
Map<String,?> claves = prefe1.getAll();
Mediante un ciclo recuperamos todas las claves y sus valores del archivo de preferencias y los almacenamos en el ArrayList con el objetivo que luego se puedan visualizar en el ListView:
for(Map.Entry<String,?> ele : claves.entrySet()){ datos.add(ele.getKey()+" : " +ele.getValue().toString()); }
Continuando en el mƩtodo onCreate creamos el ArrayAdapter y utilizamos el layout mƔs sencillo que es el que muestra solo un TextView en cada Item y lo indicamos mediante el valor android.R.layout.simple_list_item_1:
adaptador1=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, datos);
Obtenemos la referencia del ListView y le asociamos el ArrayAdapter para que pueda recibir los items a mostrar:
lv1=findViewById(R.id.list1); lv1.setAdapter(adaptador1);
Cuando se presiona el botĆ³n agregar procedemos a aƱadir un elemento al ArrayList y llamar seguidamente al mĆ©todo notifyDataSetChanged() del ArrayAdapter para que informe al ListView que actualice los datos en pantalla. Por otro lado en forma paralela procedemos a insertar una entrada en el archivo de preferencias indicando como clave el dato del et1 y como valor el valor del et2 :
public void agregar(View v) { datos.add(et1.getText().toString()+" : "+et2.getText().toString()); adaptador1.notifyDataSetChanged(); SharedPreferences.Editor elemento=prefe1.edit(); elemento.putString(et1.getText().toString(),et2.getText().toString()); elemento.commit(); et1.setText(""); et2.setText(""); }
Cuando se presiona un tiempo prolongado con el dedo un item del ListView se dispara el mĆ©todo onItemLongClick donde procedemos a mostrar un diĆ”logo para que confirme o cancele la eliminaciĆ³n del telĆ©fono seleccionado:
lv1.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) { final int posicion=i; AlertDialog.Builder dialogo1 = new AlertDialog.Builder(MainActivity.this); dialogo1.setTitle("Importante"); dialogo1.setMessage("Āæ Elimina este telĆ©fono ?"); dialogo1.setCancelable(false); dialogo1.setPositiveButton("Confirmar", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogo1, int id) { String s=datos.get(posicion); StringTokenizer tok1=new StringTokenizer(s,":"); String nom=tok1.nextToken().trim(); SharedPreferences.Editor elemento=prefe1.edit(); elemento.remove(nom); elemento.commit(); datos.remove(posicion); adaptador1.notifyDataSetChanged(); } }); dialogo1.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogo1, int id) { } }); dialogo1.show(); return false; } });
Como podemos ver cuando se presiona la opciĆ³n "Confirmar" del diĆ”logo procedemos a eliminar el elemento del ArrayList y pedir que se refresque la pantalla mediante la llamada del mĆ©todo notifyDataSetChanged del ArrayAdapter:
telefonos.remove(posicion); adaptador1.notifyDataSetChanged();
Por otro lado debemos eliminar el dato del archivo de preferencias, creamos un objeto de la clase StringTokenizer con el objetivo de dividir el nombre y el telƩfono que estƔn separados por el caracter de ":" (con la primer llamada a nextToken obtenemos el nombre del titular del telƩfono, llamamos al mƩtodo trim para eliminar el espacio en blanco que hay al final del nombre del titular):
String s=datos.get(posicion); StringTokenizer tok1=new StringTokenizer(s,":"); String nom=tok1.nextToken().trim(); SharedPreferences.Editor elemento=prefe1.edit(); elemento.remove(nom); elemento.commit();
Este proyecto lo puede descargar en un zip desde este enlace: proyecto054.zip
No hay comentarios:
Publicar un comentario