Android – EditTexts dentro de ListView vinculado a Custom ArrayAdapter – manteniendo un registro de los cambios
Tengo una actividad de Android en la que tengo un ListView enlazado a un ArrayAdapter personalizado. Cada fila del ListView tiene dos campos EditText (numérico).
El ArrayAdapter se rellena inicialmente de un DB de SQLite. Sin embargo, el usuario puede agregar una fila al final de ListView, o (pulsando una fila) borrar cualquier fila de ListView. Cuando se pulsa el botón "Guardar", sus cambios se mantienen.
- Listview con un adaptador personalizado que contiene CheckBoxes
- ListView - Imágenes barajadas al desplazarse
- Configurar RecyclerView para trabajar como chat
- Cómo configurar el color del elemento seleccionado en ListFragment en android?
- Pasar la posición en el ListView al niño RecyclerView Adapter
Estoy haciendo un seguimiento de los cambios a medida que se realizan adjuntando un CustomTextWatcher para el evento AfterTextChanged () a cada EditText en el método getView () de ArrayAdapter (pasando el EditText y el objeto correspondiente en la lista de elementos del ArrayAdapter) Propiedad de ese objeto al contenido del EditText. Esto es para que al guardar simplemente pueda iterar a través de la lista de objetos subyacente y hacer los cambios de DB apropiados, sabiendo que la lista de objetos está actualizada.
Código para la clase de adaptador y CustomTextWatcher:
private class CustomAdapter extends ArrayAdapter<DataItem> { private ArrayList<DataItem> items; public CustomAdapter(Context context, int textViewResourceId, ArrayList<DataItem> items) { super(context, textViewResourceId, items); this.items = items; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; DataItem wed = items.get(position); if (v == null) { LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.log_exercise_row, null); } if(wed != null) { EditText text1 = (EditText) v.findViewById(R.id.text1); EditText text2 = (EditText) v.findViewById(R.id.text2); text1.addTextChangedListener(new CustomTextWatcher(text1,wed)); text2.addTextChangedListener(new CustomTextWatcher(text2,wed)); int weight = wed.getWeight(); if(weight != -1) { text1.setText(weight+""); } int reps = wed.getReps(); if(reps != -1) { text2.setText(reps+""); } } return v; } private class CustomTextWatcher implements TextWatcher { private EditText EditText; private DataItem item; public CustomTextWatcher(EditText e, DataItem item) { this.EditText = e; this.item = item; } @Override public void afterTextChanged(Editable arg0) { String text = arg0.toString(); if(text != null && text.length() > 0) { int val; try { val =Integer.parseInt(text); } catch(NumberFormatException e) { val=-1; } if(EditText.getId()==R.id.weightEditText) { item.setWeight(val); } else if(EditText.getId()==R.id.repsEditText) { item.setRepetitions(val); } } }
Todo esto funciona bien, excepto cuando se agregan o eliminan elementos cuando se produce una duplicación no deseada del contenido de EditarTexto.
Para ilustrar con un ejemplo:
Comienza con 3 filas, EditText está todo vacío
En la fila 2, escriba '5', '6'
Haga clic en 'Más' -> Agrega una fila (vacía) al final. Ahora 4 filas.
Eliminar la última fila-> 3 filas se muestran, pero 2 ª y 3 ª filas ahora muestran '5', '6' -> ???????
Parece que la posición relativa de los objetos EditText dentro de ListView no es estable después de volver a enlazar que está causando el problema. Por ejemplo, el objeto EditText 'X' comienza en la posición 3 y, a continuación, después de un rebind, está en la posición 1, pero todavía tiene un CustomTextWatcher conectado a él haciendo referencia al objeto de datos en la posición 3. El otro problema es que addTextChangedListener () Afectan a los TextWatchers ya conectados al EditText.
Soy bastante nuevo para Android, así que no estoy seguro si hay un mejor enfoque para resolver mi problema. Cualquier ayuda es apreciada.
- Listview se bloquea en modo retrato cuando se hace clic en elementos (con fragmentos)
- Problema en un grupo de vistas personalizado al actualizar ListViews
- Efecto de botón de diapositiva en el elemento de vista de lista para Android
- ¿Cómo puedo agregar datos que he introducido en un cuadro de EditText en una matriz para enumerar en otra actividad?
- Android listviews: vistas de encabezado y pie de página
- Android ListView agrega elementos a la parte superior sin vista de lista desplácese
- ListView en el widget agrega aleatoriamente los elementos en el desplazamiento y el cambio de tamaño (vistas remotas anidadas)
- No puede ver datos Sqlite con adaptador simple
Parece que una clase personalizada ('ViewHolder') era lo que necesitaba para mantener las referencias entre un EditText y su objeto de datos asociados correctamente sincronizados en cada 'bind' de los datos. Además, al colocar las llamadas del detector de eventos cuando el objeto convertView era nulo en el método getView (), sólo se añadía un oyente por objeto EditText.
Gracias a http://www.vogella.de/articles/AndroidListView/article.html#listsactividad por señalarme en la dirección correcta.
public class CustomAdapter extends ArrayAdapter<DataItem> { private ArrayList<DataItem> items; private Activity Context; public CustomAdapter(Activity context, int textViewResourceId, ArrayList<DataItem> items) { super(context, textViewResourceId, items); this.items = items; this.Context = context; } static class ViewHolder { protected EditText weight; protected EditText reps; } public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; DataItem wed = items.get(position); if (v == null) { LayoutInflater inflator = Context.getLayoutInflater(); v = inflator.inflate(R.layout.log_exercise_row, null); final ViewHolder viewHolder = new ViewHolder(); viewHolder.text1 = (EditText) v.findViewById(R.id.text1); viewHolder.text2 = (EditText) v.findViewById(R.id.text2); viewHolder.text1.addTextChangedListener(new CustomTextWatcher(viewHolder, viewHolder.text1)); viewHolder.text2.addTextChangedListener(new CustomTextWatcher(viewHolder, viewHolder.text2)); v.setTag(viewHolder); viewHolder.text1.setTag(wed); viewHolder.text2.setTag(wed); } else { ViewHolder holder = (ViewHolder) v.getTag(); holder.text1.setTag(wed); holder.text2.setTag(wed); } ViewHolder holder = (ViewHolder) v.getTag(); // set values if(wed.getWeight() != -1) { holder.text1.setText(wed.getWeight()+""); } else { holder.weight.setText(""); } if(wed.getRepetitions() != -1) { holder.text2.setText(wed.getRepetitions()+""); } else { holder.reps.setText(""); } return v; }
- ¿Cómo probar la clase de aplicación con Robolectric?
- Android: evitar el bloqueo de la aplicación debido a errores no controlados