自定义ListView适配器。 TextChangedListener调用错误的EditText

时间:2012-10-01 09:35:19

标签: android listview android-edittext adapter

我有自定义适配器的旅行者列表,其中包括两个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元素时都可以,但是当我编辑第一个或最后一个元素编辑的值时,分配给List中的所有元素。在dubugger中,我看到方法afterTextChanged使用不同的position值调用了5次。 如何解决?

3 个答案:

答案 0 :(得分:3)

getView 方法中,参数位置给出新创建的 childView 的位置,而不是点击的childView的位置。

用它来获得正确的位置:

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

在任意视图onClick(View v);的{​​{1}}中。在这种情况下,您必须为该EditText实现 onTextChangedListener

这里:

myList 是ListView

v 是您单击的视图,在本例中是父视图的myView(myList)。

答案 1 :(得分:2)

问题出现是因为视图是可重用的(即在Android API中设计)。因此,最终您可以为同一文本视图分配多个文本观察程序。当文本视图中的文本发生变化时,所有已分配的观察者都会被触发。

快速修复(如果列表非常长,例如1000多个项目,则为非最佳)将是Traweller -> TextWatcher的地图。

然后在getView()内部你可以这样做(伪代码):

  • 如果此TextWatcher
  • Traweller,请检查地图
  • 如果地图没有,请创建新的TextWatcher,放入地图并分配给EditText
  • 否则将TextWatcherEditText分离并从地图中删除
  • 创建一个新的TextWatcher,放入地图并分配到EditText

答案 2 :(得分:0)

在屏幕中再创建一个名为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) {
    }
});