android listview android-edittext adapter

android - Adaptador de ListView personalizado. TextChangedListener pide un texto EditText incorrecto



android-edittext adapter (3)

en el método getView , la posición del parámetro da la posición de la vista de niño recién creada, no la posición de la vista de niño hecha clic.

usa esto para obtener la posición correcta:

final int actual_position = myList.getPositionForView((View) v.getParent());

en onClick(View v); del onClickListener de cualquier Vista. En su caso, debe implementar onTextChangedListener para ese EditText.

aquí:

myList es el ListView

v es la Vista en la que hizo clic, en este caso, la vista hija del padre (myList).

Tengo la lista de viajeros con adaptador personalizado que consiste en dos EditText - edtFirstName y edtLastName. Quiero que cuando el usuario ingrese cambios de texto guardados en la Lista, y cuando haga clic en el botón siguiente, envíe esta Lista a otra actividad.

Mi código:

public class TravellersAdapter extends BaseAdapter { private List<Traveler> itemsList; private LayoutInflater inflater; private Activity context; public TravellersAdapter(Activity context, List<Traveler> itemsList) { super(); this.itemsList = itemsList; this.context = context; inflater = LayoutInflater.from(context); } public int getCount() { return itemsList.size(); } public Object getItem(int i) { return itemsList.get(i); } public View getView(final int position, View view, ViewGroup viewGroup) { if (view == null) { view = inflater.inflate(R.layout.traveller_item, null); } Traveler currentItem = (Traveler) getItem(position); EditText firstNameView = (EditText) view.findViewById(R.id.edtFirstName); firstNameView.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable editable) { currentItem.setFirstName(editable.toString()); } }); return view; } }

Por ejemplo, List itemsList consta de 5 elementos. Cuando edito el elemento 2-4, todo está bien, pero cuando edito el primer o último elemento editado, el valor se asigna a todos los elementos de la lista. En dubugger vi ese método afterTextChanged llamadas 5 veces con diferentes valores de position . ¿Como arreglarlo?


El problema ocurre porque las vistas son reutilizables (es decir, por diseño en la API de Android). Entonces, eventualmente puede asignar más de 1 observador de texto a la misma vista de texto. Y todos los vigilantes asignados se disparan cuando se cambia el texto dentro de la vista de texto.

Una solución rápida (y no óptima si la lista es realmente larga, por ejemplo, de más de 1000 elementos) sería tener un mapa de Traweller -> TextWatcher .

Luego, dentro de getView () puedes hacer esto (pseudo-código):

  • revisa el mapa si hay un TextWatcher para este Traweller
  • si el mapa no tiene ninguno, cree un nuevo TextWatcher , TextWatcher en el mapa y EditText a EditText
  • de lo contrario, separe TextWatcher de EditText y elimínelo del mapa
  • crear un nuevo TextWatcher , ponerlo en el mapa y asignarlo a EditText

Cree uno EditText más en la pantalla que sea invisible con el nombre invivisbleEt . Y haz lo siguiente en addTextChangedListener

firstNameView.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable editable) { if(!firstNameView.isFocused()) currentItem.setFirstName(editable.toString()); } });

También agregue este código en el método onCreate para el objeto ListView .

lv.setOnScrollListener(new AbsListView.OnScrollListener() { //public boolean scrolling; @Override public void onScrollStateChanged(AbsListView absListView, int scrollState) { invivisbleEt.requestFocus(); } @Override public void onScroll(AbsListView absListView, int i, int i1, int i2) { } });