商城首页欢迎来到中国正版软件门户

您的位置:首页 >2.4.8 ListView之checkbox错位问题解决

2.4.8 ListView之checkbox错位问题解决

  发布于2026-08-12 阅读(0)

扫一扫,手机访问

本节引言:

作为ListView经典问题之一,如果你尝试过自定义ListView的item,在上面带有一个checkbox的话,那么 当你的item数超过了一页的话,就会出现这个问题,下面我们来分析下出现这种问题的原因,以及如何来 解决这个问题!

1.问题发生的原因:

这是网上找来的一幅关于ListView getView方法调用机制的一个图

上图里有一个Recycler,可以把它理解成一个用来暂存条目视图的“回收区”。平时,ListView 当前屏幕里能看到的 Item 会保留在内存中;而那些已经滑出可视区域的 Item,对应的视图就会先放进这个 Recycler。第一次加载 item 时,当前页面里的 convertView 基本都是 NULL;等条目滚出屏幕后,这时候 ConvertView 就不再为空了,于是新出现的那一项就可以直接复用这个 ConvertView。为了把这个过程看得更清楚,可以写一个简单例子,再配合 log 一起跟一下,下面这些就是运行后截到的部分 Log 图。

从图里其实已经能看出来了:当 Position 走到 12 之后,ConvertView 就不再是空的。它在这里到底对应什么,先不用死抠,真要追下去多半还是得翻源码。现阶段抓住一个关键点就够了——ConvertView 会被缓存。也正是这个缓存机制,导致了 checkbox 出现错位。于是,最直接的处理办法就是别复用这个 ConvertView,或者更干脆一点,每次执行 getView 时都把 ConvertView 置为 null。可问题在于,一旦需要展示的 Item 数量非常大,这种写法就会显得又重又笨,实际开发里通常不会这么做,更常见的还是下面这种思路:找个东东来保存当前Item CheckBox的状态,初始化的时候进行判断,设置是否选中!

2.解决方法示例:

好的存储这个Checkbox的方法有很多,你可以放到一个HashMap中, 每次初始化的时候根据postion取出对应的boolean值,然后再进行checkbox的状态设置; 而笔者的做法则是在entity类中加入了一个boolean值用于判断,下面是笔者一个项目中 抽取出来的代码,代码比较简单,相信你看完会秒懂的~

Entity类:Person.ja va

public class Person implements Serializable{
    private String name;
    private String number;
    private boolean checkStatus;
public Person(String name, String number) {
        super();
        this.name = name;
        this.number = number;
        this.checkStatus = false;
    }
public String getName() {
        return name;
    }
public void setName(String name) {
        this.name = name;
    }
public String getNumber() {
        return number;
    }
public void setNumber(String number) {
        this.number = number;
    }
public boolean getCheckStatus() {
        return checkStatus;
    }
public void setCheckStatus(boolean checkStatus) {
        this.checkStatus = checkStatus;
    }
}

实现的Adapter类:ContactListAdapter.ja va:

public class ContactListAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener{
private List mData;
    private Context mContext;
public ContactListAdapter(List data, Context context) {
        mData = data;
        mContext = context;
    }
// 定义一个刷新数据的方法
    public void changeData(List data) {
        mData = data;
        notifyDataSetChanged();
    }
@Override
    public int getCount() {
        return mData.size();
    }
@Override
    public Person getItem(int position) {
        return mData.get(position);
    }
@Override
    public long getItemId(int position) {
        return position;
    }
@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final int index = position;
        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.item_contact, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.ly = (RelativeLayout) convertView
                    .findViewById(R.id.lyContactListItem);
            viewHolder.txtName = (TextView) convertView
                    .findViewById(R.id.txtName);
            viewHolder.txtNumber = (TextView) convertView
                    .findViewById(R.id.txtNumber);
            viewHolder.cbxStatus = (CheckBox) convertView
                    .findViewById(R.id.cbxStatus);
            convertView.setTag(viewHolder);
            viewHolder.cbxStatus.setTag(index);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.cbxStatus.setOnCheckedChangeListener(this);
        viewHolder.cbxStatus.setChecked(mData.get(position).getcheckStatus());
        viewHolder.txtName.setText(mData.get(index).getName());
        viewHolder.txtNumber.setText(mData.get(index).getNumber());
        return convertView;
    }
@Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        int index = (int)buttonView.getTag();
        if (isChecked)
            mData.get(index).setCheckStatus(true);
        else
            mData.get(index).setCheckStatus(false);
    }
private class ViewHolder {
        RelativeLayout ly;
        TextView txtName;
        TextView txtNumber;
        CheckBox cbxStatus;
    }
}

嘿嘿,非常简单,另外别忘了一点: checkbox监听器的方法要添加在初始化Checkbox状态的代码之前哦~

本节引言:

好的,本节给大家讲解了ListView的一个经典问题,ListView中checkbox错位的 问题解决,只需简单的添加一个记录checkbox选择状态的值,然后重写checkbox 点击事件的时候,先做判断~谢谢~

本文转载于:https://www.runoob.com/w3cnote/android-tutorial-listview-checkbox.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注