Files
FamilyBook_harmonyos/entry/src/main/ets/components/FbSheetRing.ets
T

87 lines
3.6 KiB
Plaintext
Raw Normal View History

/**
* 家书 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 })
}
}