style(月视图): 选中态改为正圆蓝底 #6
用户要求:选中时的蓝色背景做成正圆,把日期、农历、事件点都包进去。
## 为什么第一版不圆
上一版把蓝底铺在最外层 Column 上。Column 是 layoutWeight(1) 撑满格子的
**矩形**(149×133),无论圆角给多大,只能是"圆角方块"或"胶囊",
变不成正圆。
## 这一版
新增 dayCellCircle,结构改为 Stack 叠放:
├─ 底层:选中时一个 46vp × 46vp 的正方形容器,borderRadius 50% → 真正的圆
└─ 上层:原有内容(日期数字 / 农历 / 事件点),背景透明
尺寸 46vp ≈ 138px 的依据:
· 内容实际高约 121px(日期框 75 + 农历 29 + 点 11 + 间隙)
· 格子宽 149px
⇒ 138 能包住全部内容,又不超出格子宽度
选中时日期数字、农历、事件点统一转白(与日期同色),
因为浅红压在深蓝底上会发灰。
⚠️ 踩坑记录:改这个之前最好先量一下尺寸。我是从 dump 里读到
"日期 599~674、农历 677~706、点 709~720" 才确定 46vp 这个值的,
拍脑袋给尺寸很容易包不住或溢出格子。
This commit is contained in:
@@ -1828,7 +1828,7 @@ struct Index {
|
|||||||
// false 变 true 但 key 没变 ⇒ ArkUI 复用旧组件、跳过重绘,
|
// false 变 true 但 key 没变 ⇒ ArkUI 复用旧组件、跳过重绘,
|
||||||
// 表现为"首屏农历不变红,切一次视图才正常"。
|
// 表现为"首屏农历不变红,切一次视图才正常"。
|
||||||
ForEach(week, (cell: MonthCell) => {
|
ForEach(week, (cell: MonthCell) => {
|
||||||
this.dayCell(cell)
|
this.dayCellCircle(cell)
|
||||||
}, (cell: MonthCell) => `${cell.dateMs}_${cell.dateMs === this.selectedDate}`
|
}, (cell: MonthCell) => `${cell.dateMs}_${cell.dateMs === this.selectedDate}`
|
||||||
+ `_he${cell.hasEvent ? 1 : 0}_td${cell.isToday ? 1 : 0}`)
|
+ `_he${cell.hasEvent ? 1 : 0}_td${cell.isToday ? 1 : 0}`)
|
||||||
}
|
}
|
||||||
@@ -3258,8 +3258,10 @@ struct Index {
|
|||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
dayCell(cell: MonthCell) {
|
dayCell(cell: MonthCell) {
|
||||||
// space 从 2 收到 1、日期框 26→24:格子高度原本已被"日期+农历"占满,
|
// ⭐ SEL_BLOCK 选中态:蓝底扩到整块
|
||||||
// 不收一点空间,新加的圆点会被顶出格子(实测 175px 全用尽)。
|
// 未选中 → 日期数字单独一个小蓝圈,农历灰、圆点浅红
|
||||||
|
// 选中 → 蓝底移到 Column,把农历和圆点一起圈进来,三者统一转白
|
||||||
|
// (用户要求:底变大、把农历和点包进去、颜色和日期一样)
|
||||||
Column({ space: 1 }) {
|
Column({ space: 1 }) {
|
||||||
Text(String(cell.day))
|
Text(String(cell.day))
|
||||||
.fontSize(this.wideLayout ? 12 : 13)
|
.fontSize(this.wideLayout ? 12 : 13)
|
||||||
@@ -3271,35 +3273,98 @@ struct Index {
|
|||||||
.height(this.wideLayout ? 22 : 24)
|
.height(this.wideLayout ? 22 : 24)
|
||||||
.textAlign(TextAlign.Center)
|
.textAlign(TextAlign.Center)
|
||||||
.borderRadius(this.wideLayout ? 11 : 12)
|
.borderRadius(this.wideLayout ? 11 : 12)
|
||||||
|
// 选中时背景交给外层 Column,这里必须透明,否则会出现"蓝底里套一个蓝圈"
|
||||||
.backgroundColor(cell.dateMs === this.selectedDate
|
.backgroundColor(cell.dateMs === this.selectedDate
|
||||||
? $r('app.color.selected_bg')
|
? Color.Transparent
|
||||||
|
: (cell.isToday ? $r('app.color.today_bg') : Color.Transparent))
|
||||||
|
if (!this.wideLayout) {
|
||||||
|
Text(cell.lunar)
|
||||||
|
.fontSize(8)
|
||||||
|
// 选中 → 与日期同色(白),保证在同块蓝底上都看得清
|
||||||
|
.fontColor(cell.dateMs === this.selectedDate
|
||||||
|
? $r('app.color.button_text') : $r('app.color.text_hint'))
|
||||||
|
.maxLines(1)
|
||||||
|
}
|
||||||
|
// 无事件时圆点透明但仍占位:保证有/无事件的行高完全一致,整月不会跳
|
||||||
|
// 选中时圆点也转白(与日期同色),否则浅红压在蓝底上会发灰
|
||||||
|
Circle({ width: this.wideLayout ? 4 : 3.5, height: this.wideLayout ? 4 : 3.5 })
|
||||||
|
.fill(cell.dateMs === this.selectedDate
|
||||||
|
? $r('app.color.button_text') : $r('app.color.soft_red'))
|
||||||
|
.opacity(cell.hasEvent ? 1 : 0)
|
||||||
|
}
|
||||||
|
.layoutWeight(1)
|
||||||
|
.padding({ top: this.wideLayout ? 2 : 3, bottom: this.wideLayout ? 2 : 1 })
|
||||||
|
.justifyContent(FlexAlign.Center)
|
||||||
|
.onClick(() => {
|
||||||
|
this.selectedDate = cell.dateMs;
|
||||||
|
if (!cell.inMonth) {
|
||||||
|
const d = new Date(cell.dateMs);
|
||||||
|
this.displayYear = d.getFullYear();
|
||||||
|
this.displayMonth = d.getMonth();
|
||||||
|
this.rebuildPages();
|
||||||
|
this.swiperGuard = true;
|
||||||
|
this.swiperController.changeIndex(1, false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 月视图日期格(带选中正圆背景)。
|
||||||
|
*
|
||||||
|
* ⭐ SEL_CIRCLE 为什么套一层 Stack:
|
||||||
|
* Column 是 layoutWeight(1) 撑满格子的**矩形**,无论圆角给多大
|
||||||
|
* 都只能是"方块"或"胶囊",变不成正圆。只有独立的正方形容器
|
||||||
|
* 取 50% 圆角才是真正的圆。Stack 居中叠放,圆在格子正中,内容压在上面。
|
||||||
|
*
|
||||||
|
* ⚠️ 改过两轮才定下来:
|
||||||
|
* 第一版把蓝底铺在 Column 上 → 得到 149×133 的圆角方块(用户不满意)
|
||||||
|
* 这一版用 46vp 正方形 → 真正的圆
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
dayCellCircle(cell: MonthCell) {
|
||||||
|
Stack() {
|
||||||
|
// 底层:选中时显示的正圆
|
||||||
|
if (cell.dateMs === this.selectedDate) {
|
||||||
|
Column()
|
||||||
|
.width(this.wideLayout ? 40 : 46)
|
||||||
|
.height(this.wideLayout ? 40 : 46)
|
||||||
|
.borderRadius('50%')
|
||||||
|
.backgroundColor($r('app.color.selected_bg'))
|
||||||
|
}
|
||||||
|
// 上层:原有内容(日期数字 / 农历 / 事件点)
|
||||||
|
Column({ space: 1 }) {
|
||||||
|
Text(String(cell.day))
|
||||||
|
.fontSize(this.wideLayout ? 12 : 13)
|
||||||
|
.fontWeight(cell.isToday || cell.dateMs === this.selectedDate
|
||||||
|
? FontWeight.Bold : FontWeight.Normal)
|
||||||
|
.fontColor(!cell.inMonth
|
||||||
|
? $r('app.color.text_hint')
|
||||||
|
: (cell.dateMs === this.selectedDate
|
||||||
|
? $r('app.color.button_text') : $r('app.color.text_primary')))
|
||||||
|
.width(this.wideLayout ? 22 : 24)
|
||||||
|
.height(this.wideLayout ? 22 : 24)
|
||||||
|
.textAlign(TextAlign.Center)
|
||||||
|
.borderRadius(this.wideLayout ? 11 : 12)
|
||||||
|
// 选中时背景由底层的圆负责,这里透明
|
||||||
|
.backgroundColor(cell.dateMs === this.selectedDate
|
||||||
|
? Color.Transparent
|
||||||
: (cell.isToday ? $r('app.color.today_bg') : Color.Transparent))
|
: (cell.isToday ? $r('app.color.today_bg') : Color.Transparent))
|
||||||
// ⭐ DOT_BELOW 有事件的标记 = 农历**下方**一个浅红小圆点。
|
|
||||||
//
|
|
||||||
// 视觉取舍:
|
|
||||||
// · 农历文字保持原色(灰/白),不染红 —— 整月染红不好看,用户否掉了
|
|
||||||
// · 圆点用 soft_red(浅红),不用 event_mark(#D93025) 那种警示红,
|
|
||||||
// 因为"这天有安排"是中性信息,不该有告警感
|
|
||||||
// · 点很小(3.5vp),存在感低,不抢日期数字
|
|
||||||
//
|
|
||||||
// ⚠️ 位置:放在 Column 里**独立一行**,居中。
|
|
||||||
// 上一版把点放在农历同一行的 Row 里,农历 layoutWeight(1) 撑满整行,
|
|
||||||
// 点被挤到行尾 ⇒ 贴着下一个日期,很怪。独立成行就不会跑偏。
|
|
||||||
if (!this.wideLayout) {
|
if (!this.wideLayout) {
|
||||||
Text(cell.lunar)
|
Text(cell.lunar)
|
||||||
.fontSize(8)
|
.fontSize(8)
|
||||||
.fontColor(cell.dateMs === this.selectedDate
|
.fontColor(cell.dateMs === this.selectedDate
|
||||||
? $r('app.color.text_secondary') : $r('app.color.text_hint'))
|
? $r('app.color.button_text') : $r('app.color.text_hint'))
|
||||||
.maxLines(1)
|
.maxLines(1)
|
||||||
}
|
}
|
||||||
// 无事件时圆点透明但仍占位:保证有/无事件的行高完全一致,整月不会跳
|
|
||||||
Circle({ width: this.wideLayout ? 4 : 3.5, height: this.wideLayout ? 4 : 3.5 })
|
Circle({ width: this.wideLayout ? 4 : 3.5, height: this.wideLayout ? 4 : 3.5 })
|
||||||
.fill($r('app.color.soft_red'))
|
.fill(cell.dateMs === this.selectedDate
|
||||||
|
? $r('app.color.button_text') : $r('app.color.soft_red'))
|
||||||
.opacity(cell.hasEvent ? 1 : 0)
|
.opacity(cell.hasEvent ? 1 : 0)
|
||||||
}
|
}
|
||||||
|
.justifyContent(FlexAlign.Center)
|
||||||
|
}
|
||||||
.layoutWeight(1)
|
.layoutWeight(1)
|
||||||
.padding({ top: this.wideLayout ? 2 : 3, bottom: this.wideLayout ? 2 : 3 })
|
.padding({ top: this.wideLayout ? 2 : 3, bottom: this.wideLayout ? 2 : 1 })
|
||||||
.borderRadius(8)
|
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
this.selectedDate = cell.dateMs;
|
this.selectedDate = cell.dateMs;
|
||||||
if (!cell.inMonth) {
|
if (!cell.inMonth) {
|
||||||
|
|||||||
Reference in New Issue
Block a user