87 lines
3.6 KiB
Plaintext
87 lines
3.6 KiB
Plaintext
/**
|
||||
|
|
* 家书 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 })
|
|||
|
|
}
|
|||
|
|
}
|