如何在RecyclerView适配器中获取今日位置并设置日期文本颜色
解决RecyclerView日历中日期颜色区分的问题
我明白你遇到的问题了——原来的代码里试图用布尔值day.isToday和position做比较,这肯定会报错,因为类型完全不匹配。我们需要换个思路:先找到今日在数据源列表中的位置,或者直接比较日期本身,来判断当前日期是在今日之前还是之后,再设置对应的颜色。
方案一:通过数据源索引判断(适合数据源按日期顺序排列的场景)
首先在适配器中定位今日在数据源里的索引,绑定数据时对比当前日期的索引和今日索引即可:
- 在适配器类中新增变量存储今日的索引:
private var todayIndex = -1 // 默认-1表示未找到今日数据
- 在
init块中遍历数据源,找到今日对应的位置:
init { firstDayDayOfWeek = items[0].dayOfWeek totalDays = items.size // 找到今日在items列表中的索引 todayIndex = items.indexOfFirst { it.isToday } }
- 修改
bind方法中的颜色判断逻辑:
把原来错误的if (position < day.isToday)替换成:
// 获取当前日期在items列表中的索引 val currentDayIndex = position - 7 - firstDayDayOfWeek // 判断当前日期是否在今日之前 if (todayIndex != -1 && currentDayIndex < todayIndex) { // 今日之前的日期,设置灰色 dayTxt.setTextColor(ContextCompat.getColor(context, R.color.gray)) } else { // 今日及之后的日期,设置黑色 dayTxt.setTextColor(ContextCompat.getColor(context, R.color.black)) }
方案二:直接比较日期(更健壮,推荐)
如果你的DayEntity类包含日期相关字段(比如时间戳date: Long或者LocalDate对象),直接比较日期会更可靠,能避免索引可能出现的偏差:
- 在适配器中新增变量存储今日的日期:
private var todayDate: Long? = null // 假设用Long类型时间戳,可根据实际字段调整
- 在
init块中取出今日的日期:
init { firstDayDayOfWeek = items[0].dayOfWeek totalDays = items.size // 取出今日的日期值 items.find { it.isToday }?.let { todayDate = it.date } }
- 修改
bind方法中的颜色判断:
if (todayDate != null && day.date < todayDate!!) { // 今日之前的日期,设置灰色 dayTxt.setTextColor(ContextCompat.getColor(context, R.color.gray)) } else { // 今日及之后的日期,设置黑色 dayTxt.setTextColor(ContextCompat.getColor(context, R.color.black)) }
修改后的完整适配器代码(以方案一为例)
class DaysAdapter constructor(val context: Context, private val items: MutableList<DayEntity>) : RecyclerView.Adapter<DaysAdapter.ViewHolder>() { private val TYPE_HEADER = 0 private val TYPE_DAY = 1 private var firstDayDayOfWeek = 0 private var totalDays = 0 private var todayIndex = -1 // 新增:存储今日在items中的索引 init { firstDayDayOfWeek = items[0].dayOfWeek totalDays = items.size // 找到今日的索引 todayIndex = items.indexOfFirst { it.isToday } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val inflater = LayoutInflater.from(parent.context) return ViewHolder(inflater.inflate(R.layout.item_day_new, parent, false)) } override fun getItemCount() = 7 * 7 override fun getItemViewType(position: Int): Int { return if (isPositionHeader(position)) { TYPE_HEADER } else { TYPE_DAY } } override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(position) inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private val dayTxt = itemView.findViewById(R.id.dayTxt) as TextView //Bind data fun bind(pos: Int) { var position = pos position += 6 - (position % 7) * 2 if (totalDays < position - 6 - firstDayDayOfWeek) { return } else { //Day if (!isPositionHeader(position)) { if (position - 7 - firstDayDayOfWeek >= 0) { val currentDayIndex = position - 7 - firstDayDayOfWeek val day = items[currentDayIndex] dayTxt.isVisible = true dayTxt.text = day.num // 修正后的颜色判断逻辑 if (todayIndex != -1 && currentDayIndex < todayIndex) { dayTxt.setTextColor(ContextCompat.getColor(context, R.color.gray)) } else { dayTxt.setTextColor(ContextCompat.getColor(context, R.color.black)) } } else { dayTxt.isVisible = false } } else { //Header dayTxt.text = Constants.FIRST_CHAR_OF_DAYS_OF_WEEK_NAME[position] } } } } private fun isPositionHeader(position: Int) = position < 7 }
补充说明
- 原来的代码错误核心:
day.isToday是布尔值(true/false),而position是整数,两者属于不同类型,无法直接比较。我们需要的是定位今日在数据源中的位置,或者直接对比日期实体的时间属性。 - 如果你的日历数据源是严格按日期顺序排列的,方案一足够使用;如果担心数据源调整导致索引出错,方案二的日期直接对比会更稳妥。
内容的提问来源于stack exchange,提问作者Dr.KeyOk
相关产品推荐
相关产品推荐

