3.1 KiB
3.1 KiB
玫瑰日图标设计
背景
在日历单元格上为每年 10 月 16 日 增加一个小玫瑰图标,作为纪念日标识。实现方式参考已有的生日皇冠图标配置。
目标
- 每年 10 月 16 日的单元格左上角显示玫瑰图标。
- 与生日皇冠共用同一套渲染位置、尺寸和点击动画。
- 若 10 月 16 日同时命中生日,优先显示玫瑰图标。
- 不引入额外的无障碍文本,图标仅作为视觉装饰。
方案选择
采用方案一:沿用生日模式做最小扩展。理由:
- 与现有生日代码完全同构,改动最小;
- 符合用户“参考已有生日的配置”的要求;
- 可读性最好,降低维护者理解成本。
详细设计
数据层
文件:core/src/main/kotlin/plus/rua/project/LunarCache.kt
在 DayCellInfo 中新增字段:
data class DayCellInfo(
val annotationText: String,
val isAnnotationHighlight: Boolean,
val holidayBadge: String?,
val lunarMonthName: String? = null,
val isBirthday: Boolean = false,
val isRoseDay: Boolean = false,
)
在 LunarCache.compute() 中加入玫瑰日判断:
val isRoseDay = date.month.number == 10 && date.day == 16
并将 isRoseDay 传入所有 DayCellInfo(...) 构造分支。
UI 层
文件:core/src/main/kotlin/plus/rua/project/ui/DayCell.kt
在 DayCellImpl 中:
- 读取
val isRoseDay = lunarData.isRoseDay。 - 新增
roseClickTick与roseScale状态。 - 在
clickable的onClick中:若isRoseDay则触发roseClickTick += 1,随后调用外部onClick()。 - 在
Box的左上角优先渲染玫瑰图标:- 若
isRoseDay为true,显示R.drawable.ic_rose; - 否则若
isBirthday为true,显示R.drawable.ic_birthday_crown。
- 若
- 图标尺寸、内边距与皇冠保持一致:
size(14.dp)padding(start = 2.dp, top = 2.dp)rotationZ = -45f- 点击时通过
graphicsLayer的scaleX / scaleY播放弹跳动画。
资源
- 源文件:
~/Pictures/rose-svgrepo-com.svg - 目标路径:
core/src/main/res/drawable/ic_rose.xml - 转换方式:将 SVG 转为 Android VectorDrawable,保留原始填充色,渲染时使用
Color.Unspecified。
测试
新增文件:core/src/test/kotlin/plus/rua/project/LunarCacheRoseDayTest.kt
覆盖以下场景:
LocalDate(2026, 10, 16)的isRoseDay为true。- 普通日期(如
LocalDate(2026, 6, 15))的isRoseDay为false。 - 非 10 月的 16 日(如
LocalDate(2026, 9, 16))的isRoseDay为false。
改动文件
core/src/main/kotlin/plus/rua/project/LunarCache.ktcore/src/main/kotlin/plus/rua/project/ui/DayCell.ktcore/src/main/res/drawable/ic_rose.xml(新增)core/src/test/kotlin/plus/rua/project/LunarCacheRoseDayTest.kt(新增)
风险与注意事项
- 图标与生日皇冠同位置,需确保
isRoseDay判断在前,避免被生日皇冠覆盖。 - SVG 转换后需检查
viewportWidth/viewportHeight与pathData是否正确。 - 新增字段后
DayCellInfo的copy/ 解构等用法不受影响。