点击按钮时如何检查ListView项勾选状态并获取对应Voter对象
ListView批量获取勾选项实现方案
原有代码存在三个核心问题,会导致无法正确获取勾选状态:
- Voter实体类错误存储CheckBox控件对象,列表的View是复用回收的,勾选状态属于业务数据,不能绑定在UI控件上
- getView方法中每次新建Voter对象,和适配器持有的数据源对象不统一,状态无法同步;且没有处理CheckBox的状态监听和复用状态重置,会出现滑动后勾选错乱的问题
- 若尝试遍历ListView子View获取勾选状态,会因为View回收机制漏判滚出屏幕的项,结果不可靠
按以下步骤修改即可实现需求:
第一步:修改Voter实体类
将原有的CheckBox类型字段替换为布尔类型的选中状态字段,把勾选状态作为业务数据存储:
public class Voter { private String vid; private String name; private String mNum; private String wNum; private String lmNum; private String rNum; // 存储勾选状态,替代原有的CheckBox字段 private boolean isSelected; public Voter(String vid, String name, String mNum, String wNum, String lmNum, String rNum ) { this.vid = vid; this.name = name; this.mNum = mNum; this.wNum = wNum; this.lmNum = lmNum; this.rNum = rNum; // 默认初始化为未勾选 this.isSelected = false; } public boolean isSelected() { return isSelected; } public void setSelected(boolean selected) { isSelected = selected; } // 以下字段的get/set方法保持原有逻辑不变 public String getVid() { return vid; } public void setVid(String vid) { this.vid = vid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getmNum() { return mNum; } public void setmNum(String mNum) { this.mNum = mNum; } public String getwNum() { return wNum; } public void setwNum(String wNum) { this.wNum = wNum; } public String getLmNum() { return lmNum; } public void setLmNum(String lmNum) { this.lmNum = lmNum; } public String getrNum() { return rNum; } public void setrNum(String rNum) { this.rNum = rNum; } }
第二步:修改适配器getView逻辑
移除getView中新建Voter对象的逻辑,直接使用数据源中的原对象;添加CheckBox的状态同步和监听,避免复用导致的状态错乱:
@NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { // 直接获取数据源中对应位置的Voter对象,不要新建实例 final Voter voter = getItem(position); final View result; ViewHolder holder; if(convertView == null){ LayoutInflater inflater = LayoutInflater.from(mContext); convertView = inflater.inflate(mResource, parent, false); holder = new ViewHolder(); holder.name = (TextView) convertView.findViewById(R.id.name_text_view); holder.mNum = (TextView) convertView.findViewById(R.id.mNum_text_view); holder.wNum = (TextView) convertView.findViewById(R.id.wNum_text_view); holder.lmNum = (TextView) convertView.findViewById(R.id.lmNum_text_view); holder.rNum = (TextView) convertView.findViewById(R.id.rNum_text_view); holder.vote = (CheckBox) convertView.findViewById(R.id.vote_check_box); result = convertView; convertView.setTag(holder); } else{ holder = (ViewHolder) convertView.getTag(); result = convertView; } // 先清空监听,避免View复用时触发旧监听导致状态错乱 holder.vote.setOnCheckedChangeListener(null); // 根据数据中的状态设置CheckBox显示 holder.vote.setChecked(voter.isSelected()); // 设置新的选中监听,用户操作时同步更新数据状态 holder.vote.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { voter.setSelected(isChecked); } }); // 原有动画、文本赋值逻辑保留 Animation animation = AnimationUtils.loadAnimation(mContext, (position > lastPosition) ? R.anim.loading_down_anim : R.anim.loading_up_anim); result.startAnimation(animation); lastPosition = position; holder.name.setText(voter.getName()); holder.mNum.setText(voter.getmNum()); holder.wNum.setText(voter.getwNum()); holder.lmNum.setText(voter.getLmNum()); holder.rNum.setText(voter.getrNum()); return convertView; }
第三步:按钮点击事件中获取所有勾选项
直接遍历适配器持有的数据源筛选选中项,不要遍历ListView子View:
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { List<Voter> selectedVoters = new ArrayList<>(); // 遍历适配器所有数据 for (int i = 0; i < adapter.getCount(); i++) { Voter item = adapter.getItem(i); if (item.isSelected()) { selectedVoters.add(item); } } // selectedVoters即为所有CheckBox被勾选的Voter对象集合,可直接后续业务使用 } });
内容的提问来源于stack exchange,提问作者Ashwin Jenu
相关产品推荐
相关产品推荐

