Android RecyclerView日历适配器索引越界异常修复咨询
问题修复方案
错误原因分析
你遇到的IndexOutOfBoundsException是因为索引计算逻辑错误+数据集合不完整:
- 日历RecyclerView通常需要显示6行×7列共42个日期项(包含上月补位、当月全量、下月补位日期),但你的
items集合只有30个元素(仅当月天数)。 - 代码中
newPosition -7 - items[0].dayOfWeek的计算方式,会在newPosition较大时得到超过30的索引值,直接越界访问集合。
具体修复步骤
1. 补全items集合的完整数据
确保items包含三类日期,总长度为42:
- 上月补位天数:根据当月第一天的星期数计算(比如当月1号是周三,就补周日、周一、周二3天)
- 当月所有天数
- 下月补位天数:用42减去上月补位天数和当月天数的差值
示例代码(Kotlin):
// 获取当月第一天的星期(注意:Calendar.DAY_OF_WEEK周日为1,需转成0起始) val firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1 // 上月补位天数 val prevMonthFillDays = firstDayOfWeek // 当月实际天数 val currentMonthDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) // 下月补位天数 val nextMonthFillDays = 42 - prevMonthFillDays - currentMonthDays // 构造完整items集合:上月补位 + 当月 + 下月补位 val items = mutableListOf<DayModel>() // 添加上月补位日期(这里需要根据上月最后几天生成数据) for (i in prevMonthFillDays downTo 1) { items.add(DayModel(num = (lastMonthLastDay - i + 1).toString(), isCurrentMonth = false)) } // 添加当月日期 for (i in 1..currentMonthDays) { items.add(DayModel(num = i.toString(), isCurrentMonth = true)) } // 添加下月补位日期 for (i in 1..nextMonthFillDays) { items.add(DayModel(num = i.toString(), isCurrentMonth = false)) }
2. 修正适配器的索引计算逻辑
直接根据newPosition访问items即可,因为集合已经按顺序包含了所有需要显示的日期,无需复杂计算:
override fun onBindViewHolder(holder: DaysViewHolder, position: Int) { val dayItem = items[position] holder.dayTxt.text = dayItem.num // 可选:给非当月日期设置灰色等区分样式 holder.dayTxt.setTextColor(if (dayItem.isCurrentMonth) Color.BLACK else Color.GRAY) }
如果一定要保留原有计算逻辑,必须先做边界校验(兜底方案):
val targetIndex = position -7 - items[0].dayOfWeek if (targetIndex in 0 until items.size) { holder.dayTxt.text = items[targetIndex].num } else { // 补位日期处理,比如显示空或上月/下月日期 holder.dayTxt.text = "" }
3. 统一星期起始值的计算
避免因DAY_OF_WEEK的起始值(Android中Calendar默认周日为1)导致的计算错误,统一转换为0起始(周日=0,周一=1...周六=6):
val firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1
内容的提问来源于stack exchange,提问作者Dr.KeyOk
相关产品推荐
相关产品推荐

