RecyclerView中EditText滚动丢失内容/位置错乱的解决方法咨询
解决RecyclerView中EditText滚动内容清空/错乱的问题
这个问题我太熟了——完全是RecyclerView的ViewHolder复用机制在搞事情!当列表滚动时,滑出屏幕的ViewHolder会被重新拿来显示新的列表项,如果你的EditText内容没有和数据源绑定,就会出现内容丢失或者跑到其他项里的情况。下面给你一步步解决的方案:
1. 给数据源类添加存储EditText内容的字段
首先确保你的Voltage类有两个字段,用来对应每个列表项里两个EditText的内容,这样每个项的输入都能存在自己的数据源对象里:
public class Voltage { // 保留你原来的其他字段 private String input1; // 对应第一个EditText的内容 private String input2; // 对应第二个EditText的内容 // 添加getter和setter方法 public String getInput1() { return input1; } public void setInput1(String input1) { this.input1 = input1; } public String getInput2() { return input2; } public void setInput2(String input2) { this.input2 = input2; } }
2. 修改ViewHolder,保存TextWatcher引用
因为ViewHolder会被复用,我们需要在ViewHolder里保存每个EditText的TextWatcher引用,这样下次绑定的时候可以先移除旧的监听,避免重复触发:
public static class DataViewHolder extends RecyclerView.ViewHolder { EditText editText1; EditText editText2; // 保存TextWatcher的引用,用于复用前移除监听 TextWatcher textWatcher1; TextWatcher textWatcher2; public DataViewHolder(@NonNull View itemView) { super(itemView); // 替换成你实际的EditText ID editText1 = itemView.findViewById(R.id.et_input1); editText2 = itemView.findViewById(R.id.et_input2); } }
3. 在onBindViewHolder中绑定数据+监听输入
这是最关键的一步:每次绑定ViewHolder时,先从数据源读取内容设置给EditText,然后添加TextWatcher把输入内容同步回数据源,同时要先移除旧的监听:
@Override public void onBindViewHolder(@NonNull DataViewHolder holder, int position) { Voltage currentVoltage = datas.get(position); // 从数据源读取内容,设置给EditText holder.editText1.setText(currentVoltage.getInput1()); holder.editText2.setText(currentVoltage.getInput2()); // 先移除旧的TextWatcher,防止复用导致的多次绑定 holder.editText1.removeTextChangedListener(holder.textWatcher1); holder.editText2.removeTextChangedListener(holder.textWatcher2); // 为第一个EditText创建新的监听,同步输入到数据源 holder.textWatcher1 = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} @Override public void afterTextChanged(Editable s) { // 把输入内容保存到当前的Voltage对象里 currentVoltage.setInput1(s.toString()); } }; // 第二个EditText同理 holder.textWatcher2 = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} @Override public void afterTextChanged(Editable s) { currentVoltage.setInput2(s.toString()); } }; // 添加新的TextWatcher到EditText holder.editText1.addTextChangedListener(holder.textWatcher1); holder.editText2.addTextChangedListener(holder.textWatcher2); }
额外注意点
- 当你点击按钮添加新项时,要创建新的Voltage对象并添加到
datas列表,然后调用notifyItemInserted(datas.size() - 1),这样新项有自己的数据源来存储输入内容。 - 如果你的列表有增删操作,尽量用
holder.getAdapterPosition()来获取当前项的位置,避免直接用position(因为position是绑定瞬间的位置,数据源变化后可能失效)。
这样修改后,滚动RecyclerView时,每个EditText的内容都会和对应的数据源对象绑定,再也不会出现内容清空或者错乱的问题啦!
内容的提问来源于stack exchange,提问作者Hamed
相关产品推荐
相关产品推荐

