You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fragment中SimpleAdapter实现ListView多选的视图复用问题求助

解决ListView复用导致选中状态混乱的问题

核心问题在于ListView的convertView复用机制:你直接在点击事件里临时修改View背景,但滚动时复用的View会保留之前的状态,没有根据checkedValue中的选中状态重新渲染,导致未触碰的项出现错误的视觉状态。

解决方案

不要在点击事件里直接修改View背景,而是通过自定义Adapter,在getView方法中根据checkedValue集合动态设置每个项的背景,点击事件只负责更新选中集合并通知Adapter刷新。

1. 自定义SimpleAdapter

继承系统的SimpleAdapter,重写getView方法,每次渲染项时根据当前项的RFID是否在选中集合中设置背景色:

public class CustomTagAdapter extends SimpleAdapter {
    private ArrayList<String> checkedValue;
    private Context context;

    public CustomTagAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to, ArrayList<String> checkedValue) {
        super(context, data, resource, from, to);
        this.context = context;
        this.checkedValue = checkedValue;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = super.getView(position, convertView, parent);
        // 获取当前项的RFID
        TextView tvTagUii = view.findViewById(R.id.TvTagUii);
        String rfid = tvTagUii.getText().toString();
        // 根据选中状态设置背景
        if (checkedValue.contains(rfid)) {
            view.setBackgroundColor(context.getResources().getColor(R.color.gray1));
        } else {
            view.setBackgroundColor(context.getResources().getColor(R.color.white));
        }
        return view;
    }
}

2. 替换原Adapter初始化代码

用自定义Adapter替代原SimpleAdapter,传入checkedValue集合:

checkedValue = new ArrayList<>();
LvTags = (ListView) rootView.findViewById(R.id.LvTags);
// 使用自定义Adapter
adapter = new CustomTagAdapter(getContext(), tagList, R.layout.listtag_items,
        new String[]{"tagUii", "tagacsii","tagLen", "tagCount", "tagRssi"},
        new int[]{R.id.TvTagUii, R.id.TvTagAcsii, R.id.TvTagLen, R.id.TvTagCount, R.id.TvTagRssi},
        checkedValue);
LvTags.setAdapter(adapter);

3. 修改点击事件逻辑

点击事件中只负责更新checkedValue集合,然后调用adapter.notifyDataSetChanged()通知Adapter刷新所有项的状态:

LvTags.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        TextView textView = (TextView) view.findViewById(R.id.TvTagUii);
        String RFID = textView.getText().toString();
        porcelainReceivingMessage.setText("");
        
        insqldata = checkInSql("RFID", RFID);
        if (!insqldata) {
            boolean insqlite = checkInSqlite("RFID", RFID);

            if (insqlite) {
                Toast.makeText(getContext(), "Tag in already scanned", Toast.LENGTH_SHORT).show();
            } else {
                if (checkedValue != null && checkedValue.contains(RFID)) {
                    checkedValue.remove(RFID);
                    Log.d("deselect" + position, RFID);
                } else {
                    checkedValue.add(RFID);
                    Toast.makeText(getContext(), "Long click to add this tag to scanned items", Toast.LENGTH_SHORT).show();
                    Toast.makeText(getContext(), "Item selected", Toast.LENGTH_SHORT).show();
                }
                // 更新选中数量
                selectedCount.setText(String.valueOf(checkedValue.size()));
                // 通知Adapter刷新,重新渲染所有项
                adapter.notifyDataSetChanged();
            }
        } else if (insqldata) {
            Toast.makeText(getContext(), "Tag in already in SQL DB", Toast.LENGTH_SHORT).show();
        }
        Log.d("checkedValue", String.valueOf(checkedValue));
    }
});

为什么之前的方法无效

你之前尝试的直接修改View背景、调用setItemChecked等方法,都是临时修改单个View的状态,但ListView滚动时会复用已滑出屏幕的View,这些复用的View不会自动同步checkedValue的最新状态,必须在Adapter的getView方法中每次都根据数据源重新设置,才能保证所有项显示正确的选中状态。

内容的提问来源于stack exchange,提问作者Ahsan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 18:35:17