有些时候事情往往不会像你想像的那么简单
开发过程中,我们会遇到ListView的Item里面含有Edittext的情况,希望将edittext对应的数据存到对应的条目中,比如每个商品都需要在评价的时候,留有评价信息,也就是在书写评价的时候,就将对应的评价信息放到对应商品信息中,这样避免因为Adapter在notifydatachanged刷新,所以用到了addTextChangeListener这个监听事件,在其中的方法中用来记录.下面列举其中遇到的问题:
1.焦点问题
下面是item的代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
在这里写上一个edittext
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top"
android:lines="1" />
</LinearLayout>
然后写一个普通的Adapter,运行程序会发现,点击edittext的时候 ,会出现键盘界面切换了两下,然后又消失了的状况,,这个时候应该是焦点导致了问题,所以我的解决方式是在对应的activity中
android:windowSoftInputMode="adjustResize"
这个是调整键盘弹出时edittext相对的尺寸,不同的方式有不同的效果
然后就是设置listview在滚动的时候获取焦点在失去焦点
lv_list.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
lv_list.requestFocus();//这两句话很重要
lv_list.clearFocus();
}
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
}
});
写完上述会发现不会在出现刚才那种情况了...
2.addTextChangeListener的问题
如果你用了ViewHolder的话,就会出现下面这种情况,打开程序,先
1)上下拖动Listview,然后填写第一条数据的信息,然后向下拖动,你会发现正好被重用的那条数据也显示你第一条数据
2)填写第一条数据,然后上下拖动,再回到第一条数据那里,你会发现第一条数据消失了,
,如果你觉得是复用控件导致的问题,就像是这桌吃完饭,没有刷完,等到下一波客人来的时候剩下的情景一样,那么下面这样写可能你会明白的比较透彻
//根据当前条目,获取对应数据,然后将对应的信息填写到Edittext上,
final ViewHolder viewHolder = (ViewHolder) view.getTag();
final TData tData = list.get(pos);
viewHolder.et.setText(tData.getValue() == null ? "" : tData.getValue());
这样问题就被解决了吧,可是你会发现问题仍然存在,然后添加监听事件,你会发现Edittext对应的监听事件执行了好多遍
如果这个Edittext同时被第一条数据和第十条数据复用的话,那么监听事件会执行对第一条和第十条的两个方法,所以也就是说,Edittext的addTextChangeListener的是add,而不是set的原因了,我的解决方式就是下面这样:
viewHolder.et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(final View view, boolean b) {
//根据焦点决定当前到底是谁被选中,全局变量肯定只有一个值,不会有多个值
if (b) {
view.setTag(1);
selection = pos;
} else {//这种情况主要依赖于Listview的滚动事件,抢走了焦点,也就是上面所写的滚动事件
Log.e("cxd1", "移除");
view.setTag(0);
}
}
});
viewHolder.et.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
Log.e("cxd", "beforeTextChanged");
}
//这里保存数据的时候就不会同时给多条数据赋值了
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
Log.e("cxd", "onTextChanged");
Object tag = viewHolder.et.getTag();
if (tag == null) {
return;
}
//两个条件缺一不可
if ("1".equals(tag.toString()) && pos == selection) {
Log.e("cxd", "pos=" + pos + "|||charSequence=" + charSequence.toString());
tData.setValue(charSequence.toString());
}
}
@Override
public void afterTextChanged(Editable editable) {
Log.e("cxd", "afterTextChanged");
}
});
上面的情况也可以通过removeTextChange解决,在获取焦点时调用addTextChangeListener,失去焦点时调用removeTextChange,将自身事件移除,关键在于焦点的失去那里
viewHolder.et.setInputType(inputType);
final TextWatcher textWatcher= new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
tData.setValue(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
};
viewHolder.et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(final View view, boolean b) {
if (b) {
viewHolder.et.addTextChangedListener(textWatcher);
} else {
viewHolder.et.removeTextChangedListener(textWatcher);
}
}
});