关于ListView中包含EditText数据复用引起异常的解决方案详解手机开发

概述

前几天测试提了一个bug,在ListView中添加留言信息,导致错乱的问题。实际上就是ListView需要添加一个EditText,复用导致错乱的问题,这个问题以前也遇到过。诸如,ListView嵌套EditText、CheckBox等焦点问题都会出现复用的错乱,其根源就是ViewHolder的复用问题。

这里写图片描述
说说上面的问题吧,保存item中EditText中的数据,导致数据复用的时候都给设置了值。我们在最外层存了一个Map

Map<Integer, String> edItem;

监听每个Item的输入(OnTextChangedListener),并在afterTextChanged()将值保存到Map中去。

 holder.editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { 
            @Override 
            public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { 
 
                if ((edItem.size() == inputContainer.size())) {     
                    // 添加一项控件 
                    edItem.put(edindex, "edindex"); 
                } 
 
                return false; 
            } 
        });

但是这里出现了一个问题,由于复用,导致,每一个Item都被赋值了,所以我们要解决这个问题得从源头阻断给EditText赋值,也就是在OnTextChange方法里面,我们判断一下,如果用户操作的是当前的Item,我们就给Map赋值,否则不赋值,或者赋值为空值。
所以这个时候我们要对EditText的触摸事件做监听:

editText.setOnTouchListener(new View.OnTouchListener() { 
 
            public boolean onTouch(View view, MotionEvent event) { 
                if (event.getAction() == MotionEvent.ACTION_UP) { 
                    index = position; 
                } 
                return false; 
            } 
        });

然后我们在TextWatcher的onTextChanged判断一下:

public void onTextChanged(CharSequence text, int start, int before, int count) { 
                //如果该edittext有默认内容,还要在if那里进行过滤 
 if (index>=0 && text.length() > 0 &&index== position) { 
      mData.get(index).put("input", text.toString()); 
                } 
            }

这样就解决了复用的问题,完整代码:

public class ListViewTestAdapter extends BaseAdapter { 
 
    private List<Map<String, String>> mData; 
    private LayoutInflater mInflater; 
    private Context mContext; 
 
    private int index = -1; 
 
    public ListViewTestAdapter(Context context, List<Map<String, String>> data) { 
        this.mContext = context; 
        this.mData = data; 
        this.mInflater = LayoutInflater.from(context); 
    } 
 
    @Override 
    public int getCount() { 
        return mData.size(); 
    } 
 
    @Override 
    public Object getItem(int position) { 
        return mData.get(position); 
    } 
 
    @Override 
    public long getItemId(int position) { 
        return position; 
    } 
 
    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
        ViewHolder holder = new ViewHolder(); 
        if (convertView == null) { 
            convertView = mInflater.inflate(R.layout.main_function_listitem3, null); 
            holder.title = (TextView) convertView.findViewById(R.id.txtTitle); 
            holder.editText = (EditText) convertView.findViewById(R.id.input); 
            convertView.setTag(holder); 
        } else { 
            holder = (ViewHolder) convertView.getTag(); 
        } 
 
 
        EditText editText = holder.editText; 
 
 
        editText.setOnTouchListener(new View.OnTouchListener() { 
 
            public boolean onTouch(View view, MotionEvent event) { 
 
                if (event.getAction() == MotionEvent.ACTION_UP) { 
                    index = position; 
                } 
                return false; 
            } 
        }); 
 
 
        editText.addTextChangedListener(new TextWatcher() { 
 
            public void afterTextChanged(Editable editable) { 
            } 
 
            public void beforeTextChanged(CharSequence text, int start, int count, int after) { 
            } 
 
            public void onTextChanged(CharSequence text, int start, int before, int count) { 
                //如果该edittext有默认内容,还要在if那里进行过滤 
                if (index>=0 && text.length() > 0 && index == position ) { 
                    mData.get(index).put("input", text.toString()); 
                } 
            } 
 
        }); 
        holder.title.setText(mData.get(position).get("title")); 
        holder.editText.setText(mData.get(position).get("input")); 
 
        editText.clearFocus(); 
 
        if (index != -1 && index == position) { 
 
            editText.requestFocus(); 
        } 
 
        final ViewHolder finalHolder = holder; 
        convertView.setOnClickListener(new View.OnClickListener() { 
            @Override 
            public void onClick(View v) { 
                Toast.makeText(mContext, finalHolder.title.getText(), Toast.LENGTH_SHORT).show(); 
            } 
        }); 
        return convertView; 
    } 
 
    public final class ViewHolder { 
        public TextView title; 
        public EditText editText; 
    } 
}

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/app/5663.html

(0)
上一篇 2021年7月17日 00:01
下一篇 2021年7月17日 00:01

相关推荐

发表回复

登录后才能评论