今天花了一天时间解决了一个很恶心的问题。
当listview嵌套editText,并且每一个editText都监听了setOnFocusChangeListener,当listview滑动的时候,会不断调用TextWatcher的回调方法,导致edittext的显示数据不断被刷新。
首先来看看原先的代码:
@Override
public View getView(inti, View convertView, ViewGroup viewGroup) {
.....
EditText editText =(EditText)view.findViewById(R.id.quantity);
editText.addTextChangedListener(newTextWatcher() {
.......
@Override
publicvoidafterTextChanged(Editables) {
//业务逻辑
}
return view;
}
造成afterTextChanged反复调用的原因是,listview在滑动的时候,每一个edittext的addTextChangedListener都会被按顺序被调用,并且无论你是否重用viewholder,这个现象都会出现。
(至于listview为啥反复调用这个接口,不是本文的重点)
同时,textview和edittext 只提供了removeTextChangedListener(TextWatcherwatcher);这种移除listener的方法,非常不方便。因为要持有具体的TextWatcher引用。
因此我们只能通过增加代码来解决这个问题。
这里提供两种方法,分别 适用不同的业务场景。
一、 设置flag,分别在setText前后设置,屏蔽listview滑动时刻的操作。
class ExtendWatcher implements TextWatcher {
private boolean Active = true;
void setActive(boolean active){
this.Active = active;
}
@Override
public voidbeforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public voidonTextChanged(CharSequence s, int start, int before, int count) { }
@Override
public voidafterTextChanged(Editable s) {
if (mActive) {
//业务逻辑
}
}
}
调用:
extendWatcher.setActive(false);
editText.setText(mUserDetails.get(position),BufferType.EDITABLE);
extendWatcher.setActive(true);
第二种方式,适用于editText编辑完,就需要有响应的情况。
重新定义一个EditText维护一个list,里面持有所有TextWatcher的引用
ArrayList<TextWatcher> mListeners = null;
提供一个外部清除所有TextWatcher的方法。在editText获得焦点的时候,清除所有TextWatcher,然后再添加listener,保证每一次响应的,只有一个TextWatcher响应。
代码如下:
public class ExtendedEditText extends EditText {
privateArrayList<TextWatcher> mListeners = null;
publicExtendedEditText(Context ctx) {
super(ctx);
}
publicExtendedEditText(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
}
publicExtendedEditText(Context ctx, AttributeSet attrs, int defStyle) {
super(ctx, attrs, defStyle);
}
@Override
public voidaddTextChangedListener(TextWatcher watcher) {
if(mListeners == null) {
mListeners = new ArrayList<TextWatcher>();
}
mListeners.add(watcher);
super.addTextChangedListener(watcher);
}
@Override
public voidremoveTextChangedListener(TextWatcher watcher) {
if(mListeners != null) {
inti = mListeners.indexOf(watcher);
if(i >= 0) {
mListeners.remove(i);
}
}
super.removeTextChangedListener(watcher);
}
public voidclearTextChangedListeners() {
if(mListeners != null) {
for(TextWatcher watcher : mListeners) {
super.removeTextChangedListener(watcher);
}
mListeners.clear();
mListeners = null;
}
}
大家多多指教。欢迎拍砖