自定义 ListView 适配器。 TextChangedListener 调用错误的 EditText
Posted
技术标签:
【中文标题】自定义 ListView 适配器。 TextChangedListener 调用错误的 EditText【英文标题】:Custom ListView adapter. TextChangedListener calls for wrong EditText 【发布时间】:2012-09-22 03:39:27 【问题描述】:我有带有自定义适配器的旅行者列表,其中包含两个 EditText - edtFirstName 和 edtLastName。我想要当用户输入文本时保存更改到列表,并且当下一个按钮单击时将此列表发送到另一个活动。
我的代码:
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;
例如 List itemsList 包含 5 个项目。当我编辑 2-4 个元素时一切正常,但是当我编辑第一个或最后一个元素时,编辑值分配给列表中的所有元素。在 dubugger 中,我看到该方法 afterTextChanged
以不同的 position
值调用了 5 次。
如何解决?
【问题讨论】:
您的 firstNameView 被回收用于多个项目。你的 currentItem 也是如此。 【参考方案1】:在getView方法中,参数position给出的是新创建的childView的位置,而不是被点击的childView的位置。
使用它来获得正确的位置:
final int actual_position = myList.getPositionForView((View) v.getParent());
在任何视图的onClickListener
的onClick(View v);
中。在您的情况下,您必须为该 EditText 实现 onTextChangedListener。
这里:
myList 是 ListView
v 是您点击的视图,在本例中是父视图(myList)的子视图。
【讨论】:
【参考方案2】:之所以会出现此问题,是因为视图是可重用的(这是 android API 的设计)。所以最终你可以为同一个文本视图分配超过 1 个文本观察者。当文本视图中的文本发生更改时,所有分配的观察者都会被触发。
一个快速解决方法(如果列表真的很长,比如 1000 多个项目,则不是最佳解决方案)是拥有Traweller -> TextWatcher
的映射。
然后在 getView() 内部你可以这样做(伪代码):
查看地图是否有TextWatcher
对应这个Traweller
如果map没有,则新建一个TextWatcher
,放入map并赋值给EditText
否则将 TextWatcher
从 EditText
中分离出来并从地图中删除
新建一个TextWatcher
,放入地图并分配给EditText
【讨论】:
【参考方案3】:在不可见的屏幕中再创建一个EditText
,名称为invivisbleEt
。
并在addTextChangedListener
中执行以下操作
firstNameView.addTextChangedListener(new TextWatcher()
@Override
public void afterTextChanged(Editable editable)
if(!firstNameView.isFocused())
currentItem.setFirstName(editable.toString());
);
同样在onCreate
方法中为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)
);
【讨论】:
以上是关于自定义 ListView 适配器。 TextChangedListener 调用错误的 EditText的主要内容,如果未能解决你的问题,请参考以下文章
具有包含 CheckBoxes 的自定义适配器的 Listview