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

解决RecyclerView滚动时TextView与ImageView颜色显示异常问题

解决RecyclerView滚动时TextView和图标颜色错乱的问题

你遇到的问题是RecyclerViewViewHolder复用机制导致的状态错乱,加上当前的状态存储方式(单独的toggledChoices数组)不够可靠,再加上重复创建Drawable的操作可能引发的状态残留,最终导致滚动时颜色显示错误。下面是具体的解决方案:

核心问题分析

  1. ViewHolder复用残留:RecyclerView会回收滑出屏幕的ViewHolder并重新绑定给新的数据,如果没有在每次绑定的时候完全重置所有UI状态,就会保留之前的颜色设置。
  2. 状态存储不可靠:单独的toggledChoices数组和displayedBuses数据列表可能不同步(比如列表过滤、更新时数组长度没跟上),导致状态判断错误。
  3. Drawable重复创建与共享:每次绑定都重新获取Drawable并设置颜色滤镜,没有调用mutate()会导致Drawable实例共享,颜色设置互相干扰。

具体修复步骤

1. 将状态与数据实体绑定(替代单独数组)

给BusFromToResponse添加一个isNear字段,把状态直接存在数据项里,避免数组和数据不同步的问题:

// 假设你的BusFromToResponse类,添加以下字段和方法
private boolean isNear;

public boolean isNear() {
    return isNear;
}

public void setNear(boolean near) {
    isNear = near;
}

2. 优化时间计算逻辑(避免过时API与错误)

原来的时间计算使用了过时的getHours()、getMinutes()方法,改用Calendar的标准API,同时简化时间差计算:

@Override
public void onBindViewHolder(View_Holder holder, int position) {
    BusFromToResponse bus = displayedBuses.get(position);
    Calendar currentCal = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"));
    int currentHour = currentCal.get(Calendar.HOUR_OF_DAY);
    int currentMinute = currentCal.get(Calendar.MINUTE);
    
    // 解析出发时间
    String departureTimeStr = bus.getDepartureDate().substring(
        bus.getDepartureDate().indexOf("T") + 1,
        bus.getDepartureDate().indexOf("Z") - 3
    );
    String[] depHourMin = departureTimeStr.split(":");
    int depHour = Integer.parseInt(depHourMin[0]);
    int depMin = Integer.parseInt(depHourMin[1]);
    
    // 计算30分钟后的基准时间(处理进位)
    int baseMin = depMin + 30;
    int baseHour = depHour;
    if (baseMin >= 60) {
        baseMin -= 60;
        baseHour += 1;
    }
    if (baseHour >= 24) {
        baseHour -= 24;
    }
    
    // 调用工具类判断时间差,注意要确保DateUtil.IsBigger30Min逻辑正确(考虑跨天)
    boolean isNear = DateUtil.IsBigger30Min(
        String.format("%02d:%02d", baseHour, baseMin),
        String.format("%02d:%02d", currentHour, currentMinute),
        str_date
    );
    // 将状态绑定到数据实体
    bus.setNear(isNear);
    
    // 设置显示时间
    holder.time.setText(String.format("%02d : %02d", baseHour, baseMin));
    
    // 绑定其他UI状态
    holder.onBind(bus, position);
    
    // 设置行背景色
    holder.rootView.setBackgroundColor(context.getResources().getColor(
        position % 2 == 0 ? R.color.ticket_row1 : R.color.ticket_row2
    ));
}

3. 缓存Drawable实例,避免重复创建与共享

在Adapter中提前初始化两种颜色的时钟图标,调用mutate()确保每个Drawable是独立实例:

public class BusTicketAdapter extends RecyclerView.Adapter<BusTicketAdapter.View_Holder> {
    // 添加成员变量缓存Drawable
    private Drawable yellowClockIcon;
    private Drawable whiteClockIcon;
    // ...其他成员变量
    
    public BusTicketAdapter(List<BusFromToResponse> availableBuses, Context context, String str_date, TicketListener listener) {
        // ...原有初始化代码
        // 初始化缓存的Drawable
        yellowClockIcon = ContextCompat.getDrawable(context, R.drawable.clock).mutate();
        yellowClockIcon.setColorFilter(ContextCompat.getColor(context, R.color.yellow), PorterDuff.Mode.SRC_IN);
        
        whiteClockIcon = ContextCompat.getDrawable(context, R.drawable.clock).mutate();
        whiteClockIcon.setColorFilter(ContextCompat.getColor(context, R.color.white), PorterDuff.Mode.SRC_IN);
    }
    
    // ...其他方法
}

4. 完善ViewHolder的onBind方法,确保完全重置UI状态

在onBind中直接使用数据实体的isNear状态,避免依赖不可靠的数组:

void onBind(BusFromToResponse bus, int position) {
    if (!bus.isNear()) {
        time.setTextColor(ContextCompat.getColor(context, R.color.yellow));
        clockIc.setImageDrawable(yellowClockIcon);
    } else {
        time.setTextColor(ContextCompat.getColor(context, R.color.white));
        clockIc.setImageDrawable(whiteClockIcon);
    }
}

额外注意事项

  • 检查DateUtil.IsBigger30Min的实现:确保它能正确处理跨天的时间差(比如基准时间是次日00:10,当前时间是23:50,此时时间差是20分钟,应该返回false,即显示黄色)。
  • 避免使用过时API:getHours()、getMinutes()已经被废弃,统一使用Calendar或LocalDateTime(API 26+)来处理时间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:50:58