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

基于kizitonwose Calendar的自定义CalendarView更新异常排查

解决Room事件加载到kizitonwose日历视图的图标显示问题

错误原因

当前实现存在两个核心问题:

  1. 使用全局变量eventEventType存储事件类型,遍历事件时该变量会被最后一个事件覆盖,导致所有有事件的日期都显示最后一个事件的图标。
  2. 事件加载逻辑错误:遍历事件时调用viewModel.deleteEvent会删除刚读取的事件,且未正确将日期与事件类型关联存储。

修复步骤与代码修改

1. 定义事件存储结构

在Fragment中声明一个Map,用于存储日期-事件类型的对应关系:

private val events = mutableMapOf<LocalDate, String>()

2. 修正Room事件加载逻辑

替换onViewCreated中的事件遍历代码,将事件存入Map而非删除:

// 原for循环替换为以下代码
viewModel.allEvents.forEach { item ->
    val currentDate = item.date
    val currentIssueType = item.eventType
    println("currentIssueType eventType ------------> $currentIssueType")
    // 将事件关联到对应日期
    events[currentDate] = currentIssueType
}
// 通知日历刷新视图
binding.viewCalendar.notifyCalendarChanged()

3. 修正日历DayBinder绑定逻辑

修改configureBinders中的bind方法,根据当前日期从Map中获取对应事件类型:

override fun bind(container: DayViewContainer, data: CalendarDay) {
    container.day = data
    val textView = container.binding.calendarDayText
    val dotView = container.binding.exThreeDotView

    textView.text = data.date.dayOfMonth.toString()

    if (data.position == DayPosition.MonthDate) {
        textView.makeVisible()
        when (data.date) {
            today -> {
                textView.setTextColorRes(R.color.example_3_white)
                textView.setBackgroundResource(R.drawable.day_today_bg)
                dotView.makeInVisible()
            }
            selectedDate -> {
                textView.setTextColorRes(R.color.colorPrimaryDark)
                textView.setBackgroundResource(R.drawable.day_selected_bg)
                dotView.makeInVisible()
            }
            else -> {
                // 获取当前日期对应的事件类型
                val eventType = events[data.date]
                // 根据事件类型设置图标
                eventType?.let { type ->
                    when (type) {
                        "Light" -> dotView.setImageResource(R.drawable.day_light_bg)
                        "Medium" -> dotView.setImageResource(R.drawable.day_medium_bg)
                        "Heavy" -> dotView.setImageResource(R.drawable.day_heavy_bg)
                        "Spotting" -> {
                            dotView.scaleType = ImageView.ScaleType.CENTER_INSIDE
                            dotView.setImageResource(R.drawable.day_spotting_bg)
                        }
                        "Start" -> dotView.setImageResource(R.drawable.day_start_bg)
                        "Future" -> dotView.setImageResource(R.drawable.day_future_bg)
                    }
                    dotView.makeVisible()
                } ?: dotView.makeInVisible() // 无事件则隐藏图标

                textView.setTextColorRes(R.color.example_3_black)
                textView.background = null
            }
        }
    } else {
        textView.makeInVisible()
        dotView.makeInVisible()
    }
}

Room事件加载优化建议

  1. 用LiveData监听数据变化:将ViewModel中的事件列表改为LiveData,实现数据库更新时日历自动刷新:
    // ViewModel内
    val allEventsLiveData: LiveData<List<Event>> = eventDao.getAllEvents()
    
    // Fragment内
    viewModel.allEventsLiveData.observe(viewLifecycleOwner) { eventList ->
        events.clear()
        eventList.forEach { events[it.date] = it.eventType }
        binding.viewCalendar.notifyCalendarChanged()
    }
    
  2. 移除错误的删除操作:删除viewModel.deleteEvent调用,避免丢失Room中的事件数据。
  3. 统一日期类型:确保Room实体类中日期字段使用LocalDate(配合Room的TypeConverter),与日历组件的日期类型保持一致,避免转换错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:12:18