Android Manejo de muchos campos de EditText en un ListView

Sólo una pregunta básica: si tengo varios docenas de campos de EditText que forman parte de un ListAdapter, ¿cómo pueden los campos individuales de EditText saber a qué fila pertenecen?

Actualmente estoy usando TextWatcher para escuchar la entrada de texto. He intentado extender TextWatcher de modo que pueda pasar en la posición del EditText al constructor de TextWatcher.

Sin embargo, cuando el teclado virtual aparece, las posiciones que corresponden a los diversos campos EditText se barajan.

¿Cómo puedo rastrear los campos EditText a su posición correcta?

Estoy usando un GridView para establecer las cosas. El diseño de cada elemento es un ImageView con un campo TextView y EditText debajo de él.

El texto de cada EditText se mantiene en una cadena String global denominada strings. Está inicialmente vacío y es actualizado por mi clase TextWatcher.

public void initList() { ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this, R.layout.shape, strings) { @Override public View getView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.shape, null); } final String theData = getItem(position); final EditText editText = (EditText) convertView.findViewById(R.id.shape_edittext); editText.setText(theData); editText.addTextChangedListener( new MyTextWatcher(position, editText) ); ImageView image = (ImageView) convertView.findViewById(R.id.shape_image); image.setBackgroundResource(images[position]); TextView text = (TextView) convertView.findViewById(R.id.shape_text); if (gameType == SHAPES_ABSTRACT) text.setText("Seq:"); else text.setVisibility(View.GONE); return convertView; } @Override public String getItem(int position) { return strings[position]; } }; grid.setAdapter(listAdapter); } private class MyTextWatcher implements TextWatcher { private int index; private EditText edittext; public MyTextWatcher(int index, EditText edittext) { this.index = index; this.edittext = edittext; } public void beforeTextChanged(CharSequence s, int start, int count, int after) {} public void onTextChanged(CharSequence s, int start, int before, int count) {} public void afterTextChanged(Editable s) { strings[index] = s.toString(); } public void setIndex(int newindex) { index = newindex; } } 

Cuando hago clic en el primer EditText (ver la imagen), el EditText se desplaza al uno debajo de la cara sonriente.

Muestra cómo se trazan los campos EditText

No teniendo en cuenta si se trata de un buen diseño de interfaz de usuario, aquí es cómo lo haría:

 public class TestList { public void blah() { ArrayAdapter<DataBucket> listAdapter = new ArrayAdapter<DataBucket>() { @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.testlayout, null); } final DataBucket dataBucket = getItem(position); final EditText editText = (EditText) convertView.findViewById(R.id.theText); editText.setText(dataBucket.getSomeData()); editText.addTextChangedListener(new TextWatcher() { public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } public void afterTextChanged(Editable editable) { dataBucket.setSomeData(editable.toString()); } }); return convertView; } }; } public static class DataBucket { private String someData; public String getSomeData() { return someData; } public void setSomeData(String someData) { this.someData = someData; } } } 

'DataBucket' es un marcador de posición. Necesitas usar cualquier clase que hayas creado para almacenar los datos que se ponen y editan en el texto de edición. El TextWatcher tendrá una referencia al objeto de datos referenciado. A medida que se desplaza, los cuadros de texto de edición deben actualizarse con los datos actuales y se deben guardar los cambios de texto. Es posible que desee realizar un seguimiento de qué objetos han sido modificados por el usuario para que las actualizaciones de datos y redes sean más eficientes.

* Editar *

Para utilizar una posición int en lugar de hacer referencia directamente al objeto:

 ArrayAdapter<DataBucket> listAdapter = new ArrayAdapter<DataBucket>() { @Override public View getView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.testlayout, null); } final DataBucket dataBucket = getItem(position); final EditText editText = (EditText) convertView.findViewById(R.id.theText); editText.setText(dataBucket.getSomeData()); editText.addTextChangedListener(new TextWatcher() { public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } public void afterTextChanged(Editable editable) { getItem(position).setSomeData(editable.toString()); } }); return convertView; } }; 

* Editar de nuevo *

Me siento obligado a decir para la posteridad, yo realmente no código de esta manera. Supongo que desea un poco más de datos estructurados que una matriz de cadena, y está manteniendo la matriz de cadenas fuera, así como un ArrayAdapter, por lo que su tipo de una situación extraña paralelo. Sin embargo, esto funcionará bien.

Tengo mis datos en una sola serie de la secuencia en lugar de una matriz multidimensional. La razón es porque el modelo de datos que respalda el GridView es simplemente una lista simple. Eso puede ser contraintuitivo, pero así es. GridView debe hacer el diseño en sí, y si se deja a sus propios dispositivos, se llena la fila con un número variable de células, dependiendo de la cantidad de datos que tiene y qué tan amplia es su pantalla (AFAIK).

Bastante charla. El código:

 public class TestList extends Activity { private String[] guess; //Other methods in here, onCreate, etc //Call me from somewhere else. Probably onCreate. public void initList() { ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this, /*some resourse id*/, guess) { @Override public View getView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.testlayout, null); } final String theData = getItem(position); final EditText editText = (EditText) convertView.findViewById(R.id.theText); editText.setText(theData); editText.addTextChangedListener( new MyTextWatcher(position) ); return convertView; } }; gridView.setAdapter(listAdapter); } class MyTextWatcher extends TextWatcher { private int position; public MyTextWatcher(int position) { this.position = position; } public void afterTextChanged(Editable s) { guess[position] = s.toString(); } // other methods are created, but empty } } 

Para realizar un seguimiento del número de fila, cada oyente en EditText tiene que mantener una referencia a un elemento en una lista y utilizar getPosition(item) para obtener la posición en un ListView . Mi ejemplo utiliza Button pero creo que se puede aplicar a EditText .

 class DoubleAdapter extends ArrayAdapter<Double> { public DoubleAdapter(Context context, List<Double> list) { super(context, android.R.layout.simple_list_item_1, list); } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_row, null); } // keep a reference to an item in a list final Double d = getItem(position); TextView lblId = (TextView) convertView.findViewById(R.id.lblId); lblId.setText(d.toString()); Button button1 = (Button) convertView.findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // the button listener has a reference to an item in the list // so it can know its position in the ListView int i = getPosition(d); Toast.makeText(getContext(), "" + i, Toast.LENGTH_LONG).show(); remove(d); } }); return convertView; } } 

Podría valer la pena considerar si necesita los textos de edición para ser almacenados en las celdas de la lista? Parece un poco innecesario cuando el usuario sólo va a editar uno a la vez.

Aunque no sé cómo se ha diseñado su aplicación, recomendaría que se replantee su experiencia de usuario ligeramente para que, cuando se presiona un elemento de lista, aparezca una sola edición de texto para su edición. De esa manera sólo puede obtener los elementos de lista de referencia como lo haría normalmente con un adaptador de lista, almacenarlo mientras el usuario está editando y actualizarlo cuando hayan terminado.

No estoy seguro de si es un buen diseño que tiene, ya que el contenido de EditText tendrá una buena probabilidad de tener problemas (barajar el contenido, el texto que falta) una vez que su lista se desplaza. Considerar probar la idea de m6tt.

Pero si realmente quieres ir a tu manera, ¿puedes publicar algún código, específicamente de tu TextWatcher?

Traté de resolver esto y como se puede ver hay un método simple – Estoy publicando la respuesta aquí, ya que podría ser útil para alguien.

No es capaz de obtener la posición cuando la vista de lista -> editar texto tiene un observador de texto.

Esta es la solución que funcionó para mí:

En obtener vista –

Cuando agrego el oyente del watcher del texto para corregir el texto, también agregué la línea abajo

 edittext.setTag(R.id.position<any unique string identitiy>, position) 

En su afterTextChanged –

  int position = edittext.getTag(R.id.position) 

Da el número de posición correcto y puede hacer modificaciones basadas en el número de posición.

  • Cómo hacer TextWatcher esperar un tiempo antes de hacer algo de acción
  • Formatear el número de teléfono de EditText como tipos de usuario
  • AutocompleteTextView dinámico con ArrayAdapter y TextWatcher
  • Espaciado de letras en EditText para Android
  • No se puede insertar en Editable
  • Quitar TextChangedListener y volver a agregarlo
  • Android edittext onchange escucha
  • ¿Cómo usar la clase TextWatcher en Android?
  • Agregar automáticamente guión en el número de teléfono en Android
  • EditText no se actualiza después de que se cambió el texto en TextWatcher
  • Android TextWatcher.afterTextChanged vs TextWatcher.onTextChanged
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.