feat(待办): 选择器改为居中弹层 + 对勾改矢量绘制 (#50)

## 1. 时间选择器改为屏幕居中弹出

### 用户诉求
「点完开始之后,在中间弹出一个框来选择时间,操作起来更方便」

### 为什么不用 bindSheet
查 SDK `SheetOptions`(common.d.ts:11753)确认:**没有 position / alignment 参数**,
bindSheet 只能从底部弹,无法居中。

### 做法:自绘居中覆盖层
把 build() 根节点改为 `Stack`:
  Stack(alignContent: Center) {
    Column { 顶部栏 + Scroll 表单 }   ← 原有内容
    if (sheetShow) {
      遮罩(半透明,点空白关闭)
      centerDialog()                   ← 居中卡片
    }
  }

选这条路而不是 CustomDialogController,依据是本工程 MEMORY:
系统弹层在本环境曾"静默失败"(Index.ets:1421 已记录),
首启引导页 tipsOverlay 就是改用自绘覆盖层才可靠的。

## 2. 对勾改为矢量 Path

### 问题
原来用字符 `✓`(U+2713),三个毛病:
- 字体依赖:不同设备粗细/形状不同
- 粗细不可控:fontWeight 对符号字形影响有限
- 居中不稳:字形基线导致视觉重心偏移

### 改法
用 `Path` 画折线,配 strokeWidth + 圆头圆角:
  commands('M6 12.5 L9.5 16 L16.5 8')  // 22vp 列表
  commands('M5 9.5 L7.5 12.5 L13 6.5') // 18vp 时间轴
得到粗细均匀、端点圆润、可精确居中的勾。

两处统一:待办列表勾选圈、时间轴待办区勾选圈。

## 编译
BUILD SUCCESSFUL

## 真机验证(5NC0225B27004718)
| 验证项 | 实测 |
|---|---|
| 弹层居中 | 弹层 y 750~1728,中心 **1239**;屏幕中心 1222,偏差仅 17px |
| 对比改造前 | 中心 1800(偏下 578px)→ 现在偏 17px |
| 日期/时间滚轮 | `DatePicker 2026年11月5日` + `TimePicker 09:00` 正常渲染 |
| 对勾 Path 数量 | 1 个 `[96,2013][165,2082]` |
| 字符 ✓ 残留 | 0 个 |
This commit is contained in:
2026-11-05 10:55:15 +08:00
parent 007c112af2
commit 39337a5530
2 changed files with 87 additions and 44 deletions
+40 -20
View File
@@ -3498,14 +3498,24 @@ struct Index {
// 勾选框(颜色跟随日历本)—— **只有这块触发完成切换**
Row() {
if (t.completed) {
Text('✓')
.fontSize(13)
.fontColor($r('app.color.button_text'))
.width(22)
.height(22)
.textAlign(TextAlign.Center)
.borderRadius(11)
.backgroundColor(this.colorOfCal(t.calKey))
// ⭐ 用矢量 Path 画勾(#50):字符 '✓' 依赖字体,
// 不同设备下粗细/居中不一致,视觉上"不精致"。
// Path 可精确控制线宽、端点圆角与几何比例。
Stack() {
Path()
.width(22)
.height(22)
.commands('M6 12.5 L9.5 16 L16.5 8')
.stroke($r('app.color.button_text'))
.strokeWidth(2.2)
.strokeLineCap(LineCapStyle.Round)
.strokeLineJoin(LineJoinStyle.Round)
.fill(Color.Transparent)
}
.width(22)
.height(22)
.borderRadius(11)
.backgroundColor(this.colorOfCal(t.calKey))
} else {
Text('')
.width(22)
@@ -4594,18 +4604,28 @@ struct DayTimelineView {
ForEach(this.timeline.todos, (td: DisplayEvent) => {
Row({ space: 8 }) {
// 勾选圈:点击切换完成(与待办列表同一回调)
Text(td.completed ? '✓' : '')
.fontSize(12)
.fontColor(td.completed ? '#FFFFFF' : 'rgba(0,0,0,0)')
.width(18)
.height(18)
.textAlign(TextAlign.Center)
.borderRadius(9)
.backgroundColor(td.completed ? td.color : 'rgba(0,0,0,0)')
.border({ width: 1.5, color: td.color })
.onClick(() => {
this.onToggleTodo(td);
})
// 同列表:矢量勾(#50)
Stack() {
if (td.completed) {
Path()
.width(18)
.height(18)
.commands('M5 9.5 L7.5 12.5 L13 6.5')
.stroke('#FFFFFF')
.strokeWidth(2)
.strokeLineCap(LineCapStyle.Round)
.strokeLineJoin(LineJoinStyle.Round)
.fill(Color.Transparent)
}
}
.width(18)
.height(18)
.borderRadius(9)
.backgroundColor(td.completed ? td.color : 'rgba(0,0,0,0)')
.border({ width: 1.5, color: td.color })
.onClick(() => {
this.onToggleTodo(td);
})
Text(td.title === '' ? '(无标题待办)' : td.title)
.fontSize(12)
.fontColor($r('app.color.text_primary'))