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 esteTraweller
- si el mapa no tiene ninguno, cree un nuevo
TextWatcher
,TextWatcher
en el mapa yEditText
aEditText
- de lo contrario, separe
TextWatcher
deEditText
y elimínelo del mapa - crear un nuevo
TextWatcher
, ponerlo en el mapa y asignarlo aEditText
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) {
}
});