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

ListView多选条目点击变色异常:滚动后非目标条目错误染色

解决ListView条目点击变色(支持多选)且滚动后无错误染色的问题

这个问题的核心原因是ListView的View复用机制:你之前直接修改View的背景色,当滚动时,已经被修改颜色的View会被复用到新进入可视区域的条目上,导致非目标条目也变色。要解决这个问题,必须把选中状态和数据源绑定,而不是直接操作View。

下面是完整的解决方案,完美支持多选场景:

步骤1:给数据源添加选中状态字段

首先,在存储列表数据的contactList(JSONArray)中,给每个JSONObject添加一个isSelected布尔字段,用来标记该条目是否被选中,默认值为false。

// 假设你是从原始JSONArray初始化contactList的,修改初始化逻辑:
JSONArray jsonArray = ...; // 你的原始数据数组
contactList = new JSONArray();
for (int i = 0; i < jsonArray.length(); i++) {
    JSONObject item = jsonArray.getJSONObject(i);
    item.put("isSelected", false); // 添加选中状态标记
    contactList.put(item);
}

步骤2:修改Adapter的getView方法,根据数据渲染背景色

在Adapter的getView方法中,不再依赖View的现有状态,而是直接从数据源获取isSelected字段,以此设置条目背景色。这样View复用时,会根据当前条目的数据重新渲染,不会保留之前的颜色。

public View getView(final int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    if (convertView == null) {
        convertView = layoutInflater.inflate(R.layout.list_date, null);
        holder = new ViewHolder();
        holder.text = (TextView) convertView.findViewById(R.id.email);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    try {
        JSONObject c = contactList.getJSONObject(position);
        String slots = c.getString("slot1");
        holder.text.setText(slots);
        
        // 根据数据源的选中状态设置背景色
        boolean isSelected = c.getBoolean("isSelected");
        if (isSelected) {
            convertView.setBackgroundColor(Color.parseColor("#ff39fff7"));
        } else {
            convertView.setBackgroundColor(Color.WHITE);
        }
    } catch (final JSONException e) {
        Log.e(TAG, "Json parsing error: " + e.getMessage());
    }
    return convertView;
}

步骤3:修改ListView点击事件,更新数据源并刷新Adapter

点击条目时,不再直接修改View的颜色,而是切换对应数据源条目的isSelected状态,然后通知Adapter刷新,让getView重新渲染该条目。

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        try {
            JSONObject item = contactList.getJSONObject(position);
            String slot1 = item.getString("slot1");
            
            // 处理不可选的情况
            if (slot1.isEmpty()) {
                selectedtime.setText("not available");
                return;
            }
            
            // 切换当前条目的选中状态
            boolean currentState = item.getBoolean("isSelected");
            item.put("isSelected", !currentState);
            
            // 通知Adapter刷新数据,触发getView重新渲染
            ((BaseAdapter) lv.getAdapter()).notifyDataSetChanged();
            
            // 更新选中时间的显示(可选)
            String date = item.getString("date");
            selectedtime.setText(slot1 + " - " + date);
            
        } catch (JSONException e) {
            Log.e(TAG, "Json parsing error: " + e.getMessage());
        }
    }
});

额外的代码优化提示

  • 避免用==比较字符串:比如之前的listOfValues.get(0) == "",应该替换为listOfValues.get(0).isEmpty()或者listOfValues.get(0).equals(""),因为==比较的是对象引用,不是字符串内容。
  • 移除不必要的getViewByPosition调用:点击事件中的position就是数据源的正确索引,直接操作数据源即可,不需要通过位置获取View。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:48:42