ListView点击首行RadioButton后滚动时其他行按钮误选中的解决方法
我在ListView的每个item里放置了3个RadioButton,点击首行的RadioButton后,向下滚动ListView时,发现其他行的RadioButton也会被莫名选中,具体情况如下:
【首行RadioButton被选中】
【滚动后另一行RadioButton被选中】
以下是我当前的适配器代码:
@Override public View getView(final int position, View convertView, final ViewGroup parent) { final ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.item_listview, null); holder.tvAlat = (TextView) convertView.findViewById(R.id.tv_alat); holder.tvpengecekan = (TextView) convertView.findViewById(R.id.tv_pengecekan); holder.tvnormal = (TextView) convertView.findViewById(R.id.tv_normal); convertView.setTag(mPengecekanList.get(position).getId_pengecekan()); holder.baik = (RadioButton) convertView.findViewById(R.id.B); holder.rusakringan = (RadioButton) convertView.findViewById(R.id.RR); holder.rusakberat = (RadioButton) convertView.findViewById(R.id.RB); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.tvAlat.setText(mPengecekanList.get(position).getNama_alat()); holder.tvpengecekan.setText(mPengecekanList.get(position).getPengecekan()); holder.tvnormal.setText(mPengecekanList.get(position).getNormal()); holder.baik.setTag(position); holder.rusakringan.setTag(position); holder.rusakberat.setTag(position); holder.baik.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { selectedAnswers.set(position, "1"); } }); holder.rusakringan.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { selectedAnswers.set(position, "2"); } }); holder.rusakberat.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { selectedAnswers.set(position, "3"); } }); }
问题原因
这是ListView的视图复用机制在搞鬼!ListView为了提升性能,会重复使用已经滑出屏幕的item视图(也就是convertView)。你现在只在点击RadioButton时把选中状态存到了selectedAnswers集合里,但没有在每次复用视图时,根据集合里的真实状态去更新RadioButton的选中状态,所以旧视图里的选中状态就被带到了新的item上。
解决步骤
- 在getView方法末尾添加状态刷新逻辑:每次渲染item时,根据
selectedAnswers里保存的值,手动设置对应RadioButton的选中状态,覆盖复用视图的旧状态。 - 修复ViewHolder的tag冲突问题:你之前在convertView为null时先设置了id为tag,之后又把holder设为tag,这会覆盖之前的tag,建议把id字段放到ViewHolder里。
- 补上getView的返回值:你原来的代码漏掉了返回convertView,这也会导致视图渲染异常。
修改后的完整代码片段
// 先给ViewHolder添加id字段 static class ViewHolder { TextView tvAlat; TextView tvpengecekan; TextView tvnormal; RadioButton baik; RadioButton rusakringan; RadioButton rusakberat; String idPengecekan; // 新增字段存储id } @Override public View getView(final int position, View convertView, final ViewGroup parent) { final ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.item_listview, null); holder.tvAlat = (TextView) convertView.findViewById(R.id.tv_alat); holder.tvpengecekan = (TextView) convertView.findViewById(R.id.tv_pengecekan); holder.tvnormal = (TextView) convertView.findViewById(R.id.tv_normal); holder.baik = (RadioButton) convertView.findViewById(R.id.B); holder.rusakringan = (RadioButton) convertView.findViewById(R.id.RR); holder.rusakberat = (RadioButton) convertView.findViewById(R.id.RB); // 把id存到ViewHolder里,不再单独设置tag holder.idPengecekan = mPengecekanList.get(position).getId_pengecekan(); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.tvAlat.setText(mPengecekanList.get(position).getNama_alat()); holder.tvpengecekan.setText(mPengecekanList.get(position).getPengecekan()); holder.tvnormal.setText(mPengecekanList.get(position).getNormal()); holder.baik.setTag(position); holder.rusakringan.setTag(position); holder.rusakberat.setTag(position); holder.baik.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { selectedAnswers.set(position, "1"); } }); holder.rusakringan.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { selectedAnswers.set(position, "2"); } }); holder.rusakberat.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { selectedAnswers.set(position, "3"); } }); // 关键:根据保存的状态刷新RadioButton String currentAnswer = selectedAnswers.get(position); if (currentAnswer != null) { holder.baik.setChecked("1".equals(currentAnswer)); holder.rusakringan.setChecked("2".equals(currentAnswer)); holder.rusakberat.setChecked("3".equals(currentAnswer)); } else { // 如果没有选中状态,默认都不选 holder.baik.setChecked(false); holder.rusakringan.setChecked(false); holder.rusakberat.setChecked(false); } return convertView; // 补上返回值 }
这样修改后,每次复用视图时都会根据selectedAnswers里的真实数据刷新RadioButton状态,滚动时就不会出现选中状态混乱的问题了。
内容的提问来源于stack exchange,提问作者Ibg Teguh
相关产品推荐
相关产品推荐

