Files
FamilyBook_harmonyos/entry/src/main/ets/components/FbSheetRing.ets
T
laoyang 1a67247407 v60b:所有弹框统一主题色描边环 + 编辑改居中弹框 + 修名册下拉回弹吃掉悬浮栏
1)9 个浮层统一描边环(抽组件,不复制 8 遍)
   新增 components/FbSheetRing.ets:环宽 FB_RING_W=2 全工程唯一一处;
   实现是"外层 Column 铺色 + padding",不是 border(border 画在盒子内侧);
   外圆角 = 内圆角 + 环宽。简要卡/详情/编辑/日程详情/日程编辑/观影详情/影院/
   日程设置/模块设置全部改用;各浮层的环色 = 所属模块的主题色。

2)编辑从"贴底满宽 + 只有上圆角"改成居中弹框
   人员编辑与日程编辑:Stack 对齐改 Center,卡片 92% 宽 + 四角圆 + 环;
   constraintSize 留在卡片自己身上(挪到外层会让内层 Scroll().layoutWeight
   拿到 0 高度,资料区塌成一条线)。日程的日期时间选择弹层、两个删除确认框
   一并套环,避免同一次交互里出现两种形态。

3)修名册下拉到头回弹后悬浮按钮消失
   EdgeEffect.Spring 在越界松手后把内容弹回,每帧 offset>0 被当成"用户在往上滑"
   ⇒ 收起悬浮栏。判据 = 手指已抬起 + 最后一次方向是下滑 + 抬手不到 500ms;
   拦截必须排在 offset >= HIDE_AT 快路径之前(回弹第一帧位移常 >= 12vp)。

4)真机截图暴露的两个观感问题(静态检查全绿也照错)
   - Scroll().layoutWeight(1) 让短内容也撑满 maxHeight ⇒ 卡片空半屏
     (日程详情/模块设置),改为 flexShrink(1);内容本来就长的浮层不动。
   - 人员编辑"虚拟人物(还没弄清真实身份)"被卡片裁掉半句:两个小开关从
     并排 Row 改为 Flex(wrap) 换行,间距改走 margin。

验证:ArkTS 守卫 444/0;反向验证 17/17;真机 _fb_v60b_verify.py 11/0,
且关掉回弹拦截重编重装后该用例确实变红(证明测试不是假绿);
9 个浮层逐个真机截图确认。
2026-10-19 08:29:44 +08:00

87 lines
3.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 家书 FamilyBook · 浮层卡片的「主题色描边环」统一容器(鸿蒙端)
*
* 🔴 用户 2026-10-19 原话:
* 「既然弹框加了线,那就**所有弹框都加线**,编辑,也弄成弹框,加线,保持一致。」
*
* ⇒ 以前只有「简要卡」自己手写了一层环(外层 `Column` 铺色 + `padding` + 内层白卡)。
* 手写一次没问题,**手写十次必然漂移**(环宽/圆角/阴影/边距一处一个样)——
* 所以抽成这个组件:**所有浮层都套它**,环宽和圆角只在这里定义。
*
* ⚠️ 为什么是"外层铺色 + 内边距",而不是给白卡加 `border`:
* `border` 画在**盒子内侧**,会把卡片内容区撑窄 2vp,且圆角处顺着**内圆角**走,
* 看着像"白卡描了彩边";用户要的是"**外面**加一圈" ⇒ 必须垫一层。
* (`FbPersonQuickSheet` 第一版就踩过,注释里留着证据。)
*
* ⚠️ `clip(true)` 不是装饰:卡片内部有 `Scroll`(详情/编辑都很长),
* 不裁的话滚动内容会**越过圆角**画到环上,看着像"内容从卡片里漏出来"。
* 如果调用方内部还要往外"溢出显示"(如全屏图片查看器),传 `clipContent: false`
* —— 并且查看器必须放在**这个组件之外**的兄弟层(现在 `FbMovieDetailSheet` 就是这么做的)。
*
* ⚠️ 本组件只管"外观"(宽度由调用方给、内容由尾随闭包给):
* 它**不设** maxHeight / padding / 背景层次 —— 那些属于各卡片自己的版式。
*/
import { FbColors, FbMetric, FB_SHADOW, FbTint } from '../common/Theme';
/**
* 环的宽度(vp)—— **全应用唯一一处定义**。
*
* ⚠️ 2vp 是"看得见但不喧哗"的那一档:1vp 在深色遮罩上仍显得细弱(真机上像一条发丝),
* 3vp 以上就变成"彩色相框",抢了内容和按钮的注意力。
* ⚠️ 内层圆角 = `radius`,外层圆角 = `radius + 环宽`:
* 两圈同心圆角的差值必须正好等于环宽,否则环在内侧显厚、外侧显薄(看着像描边歪了)。
*/
export const FB_RING_W: number = 2;
@ComponentV2
export struct FbSheetRing {
/** 卡片(内层)圆角;环层自动 +FB_RING_W */
@Param radius: number = FbMetric.radius;
/**
* 环的颜色 —— 各模块的主题色(砖红 / 青 / 靛蓝…)。
*
* ⚠️ 必须是 **hex 字符串**(不能用 `Resource`):这里要直接当背景色用,
* 而默认值在 ArkTS 里也必须是常量表达式。
*/
@Param ringColor: string = FbTint.brand;
/**
* 阴影半径(vp)。0 = **不画阴影**。
*
* ⚠️ 嵌在别的卡片里时(顶栏「我的资料」塞进 bindSheet)要传 0:
* 宿主已经有自己的容器与投影,再叠一层会显得脏。
*/
@Param shadowRadius: number = 24;
/**
* 是否裁剪内容到圆角。
*
* 默认 `true`;只有在卡片内部还有"要溢出显示"的层时传 `false`
* (见文件头 `clip` 的说明)。
*/
@Param clipContent: boolean = true;
/** 卡片本体(尾随闭包传入) */
@BuilderParam content: () => void;
build() {
Column() {
Column() {
this.content()
}
.width('100%')
.backgroundColor(FbColors.surface)
.borderRadius(this.radius)
.clip(this.clipContent)
}
.width('100%')
.padding(FB_RING_W)
.backgroundColor(this.ringColor)
.borderRadius(this.radius + FB_RING_W)
.alignItems(HorizontalAlign.Center)
.shadow({ radius: this.shadowRadius, color: FB_SHADOW, offsetX: 0, offsetY: 6 })
}
}