下拉框与网页端对齐(照 FeedLite 那套观感)(#86)
用户 2026-11-05:「好了,鸿蒙端也用类似的方式调,效果让它保持一致。」 端上**不需要像网页那样手写浮层** —— 网页端必须自绘是因为 「原生 select 的展开列表由浏览器绘制,CSS 改不动」; ArkUI 的 Select 本身就是自绘的、选项列表也归框架管。 ⇒ 把对应属性都设上就等价了: 网页端 ArkUI Select ────────────────────────────────────────────────────── 按钮 40 高 / 圆角 / 细边框 height(40) + borderRadius + border 箭头打开转 180° 框架内置(自带动画) 悬停 tint-1 不支持(触屏没有 hover)→ 用打开态代替 选中项底 tint-2 selectedOptionBgColor(fbMixWhite(accent,0.80)) 选中项文字 主题色 selectedOptionFontColor(accent) 选中项右侧对勾 showDefaultSelectedIcon(true) 浮层白底 + 细边框 menuBackgroundColor(White) + border 浮层与按钮同宽 optionWidth(OptionWidthMode.FIT_TRIGGER) 未选值次要色 fontColor(有值 ? accent : Faint) ① Theme 新增 fbMixWhite(hex, ratio) 与网页端 fb_color_tint() **同算法同比例**(混 91/80/72% 白)。 ⚠️ 为什么不用现成的 fbAlpha():那是「原色 + 透明度」, 会透出父容器底色 —— 下拉浮层背景不确定,那样会时深时浅; 这里是实色混合,颜色确定。 ⚠️ 实测 16 组(4 个主题色 × 4 档比例)与 PHP 输出逐个比对,全部一致。 ② 边框单独用一档 按钮边框 fbMixWhite(accent, 0.62) —— 比 tint-3 再深一点, 否则在 tint-1 的浅底上几乎看不见边界。 ③ 修一个类型坑 本来写了个 pickFontColor(): string 返回 accent / FbColors.muted, 但 FbColors.muted 是 Resource($r(...)),返回 string | Resource 会让 fontColor() 报「Type 'string | Resource' is not assignable to 'string'」。 ⇒ 改成内联三元,且未选用 FbColors.faint(那个是 string 常量)。 编译通过,已装真机。
This commit is contained in:
@@ -386,6 +386,61 @@ function fbIconOf(name: string): Resource {
|
||||
* @param hex 六位十六进制(`#RRGGBB`;也容忍八位,会先截成前六位)
|
||||
* @param alpha 0~1(0.4 = 40% 不透明)
|
||||
*/
|
||||
/**
|
||||
* 把主题色往白色方向混,得到一档浅色。
|
||||
*
|
||||
* 🔴 #86(用户 2026-11-05):「鸿蒙端也用类似的方式调,效果让它保持一致。」
|
||||
*
|
||||
* 与网页端 `fb_color_tint()`(app/helpers.php)**必须是同一个算法**,
|
||||
* 否则同一条任务在两端的下拉项颜色不一样 —— 那就白"保持一致"了。
|
||||
*
|
||||
* 网页端的三档:
|
||||
* tint-1(混 91% 白)→ 悬停 / 打开态底
|
||||
* tint-2(混 80% 白)→ 选中项底
|
||||
* tint-3(混 72% 白)→ 选中项悬停
|
||||
*
|
||||
* ⚠️ 与 `fbAlpha()` 的区别:那个是"原色 + 透明度"(透出背景色,会受
|
||||
* 父容器底色影响);这个是"实色混合"(不透明,颜色确定)。
|
||||
* 下拉项底色必须用实色 —— 用透明度的话叠在白色面板上还行,
|
||||
* 但它自己是浮层,背景不确定,会时深时浅。
|
||||
*
|
||||
* @param hex 六位十六进制(`#RRGGBB`)
|
||||
* @param ratio 往白色混多少(0.91 = 91% 白 + 9% 原色)
|
||||
*/
|
||||
export function fbMixWhite(hex: string, ratio: number): string {
|
||||
let base: string = hex.trim();
|
||||
if (base.startsWith('#')) {
|
||||
base = base.substring(1);
|
||||
}
|
||||
if (base.length > 6) {
|
||||
base = base.substring(base.length - 6);
|
||||
}
|
||||
if (base.length !== 6) {
|
||||
return hex; // 不是 6 位 hex(如 rgba())→ 原样返回,调用方自己兜底
|
||||
}
|
||||
const r: number = parseInt(base.substring(0, 2), 16);
|
||||
const g: number = parseInt(base.substring(2, 4), 16);
|
||||
const b: number = parseInt(base.substring(4, 6), 16);
|
||||
if (isNaN(r) || isNaN(g) || isNaN(b)) {
|
||||
return hex;
|
||||
}
|
||||
let q: number = ratio;
|
||||
if (q < 0) {
|
||||
q = 0;
|
||||
}
|
||||
if (q > 1) {
|
||||
q = 1;
|
||||
}
|
||||
const nr: number = Math.round(r + (255 - r) * q);
|
||||
const ng: number = Math.round(g + (255 - g) * q);
|
||||
const nb: number = Math.round(b + (255 - b) * q);
|
||||
const h2 = (v: number): string => {
|
||||
const s2: string = v.toString(16).toUpperCase();
|
||||
return s2.length < 2 ? '0' + s2 : s2;
|
||||
};
|
||||
return '#' + h2(nr) + h2(ng) + h2(nb);
|
||||
}
|
||||
|
||||
export function fbAlpha(hex: string, alpha: number): string {
|
||||
let base: string = hex.trim();
|
||||
if (base.startsWith('#')) {
|
||||
|
||||
Reference in New Issue
Block a user