修「名册卡片右侧贴屏幕」的真凶:width('100%') 与 margin 打架(不是 flexShrink)

真机实测纠正了我第一轮的误判。

现象(用户):「名册列表左侧有空隙了……怎么右侧不是呢?右侧还是紧贴屏幕。」
像素实测:左米色 52~72px、**右米色 0px**;布局树里卡片盒子 x = **50~1080**。

🔴 真根因:卡片**同时**写了
    .width('100%')
    .margin({ left: 16, right: 16 })
  `100%` 是相对**父容器全宽**(= 屏宽 1080),margin 再把盒子往右推
  ⇒ 盒子变成 50~1080(左边留 50、右边 0)—— 正是用户看到的形态。
  ⇒ 去掉 `.width('100%')`,Row 按"父宽 − margin"自适应,两边都是 16。
  真机复验:卡片盒子 x = 50~**1030**(左右各 50,对称);
            像素扫描 y=860/880/1090/1310 全部 **左=右**。

⚠️ 我第一轮误判成"内容把卡片撑破",去加了 `flexShrink(1)` —— 那是**错的**:
   `flexShrink` 防的是"长名字把同行的小标签挤没",与本 bug 无关。
   真正的证据是**布局树里卡片自己的 x 是 50~1080**(不是子节点越界)。
   ⇒ 教训:**先量"卡片本身"的盒子,再怀疑子节点。**
   (`flexShrink` 保留 —— 它本身是有价值的防护,但注释已改正,
     不再宣称它是本 bug 的修法。)

验证:hvigor BUILD SUCCESSFUL;_fb_arkts_guard.js 378/0;
_fb_v59c_falsify.py 16/0(本批新增第 16 项注入:把 width('100%') 加回卡片,
必须被抓住。该判据本身也反复调了三轮才既不恒红、又能抓住注入:
"别处也有" ⇒ 恒红;"取卡片尾部窗口" ⇒ 覆盖不到注入点;
"取 personRow 整段" ⇒ 段里天然含 4 处 width(3 处在注释里)⇒ 基线红;
最终 = **剥注释 + 只看卡片自己那一层**)。
This commit is contained in:
2026-10-18 21:56:34 +08:00
parent 412d2ae2f7
commit 1c1a859464
@@ -1035,14 +1035,10 @@ export struct FbPeoplePage {
.fontColor(FbColors.ink)
.fontWeight(FontWeight.Medium)
.maxLines(1)
/* 🔴🔴 内容必须**允许收缩**(`flexShrink`),否则会把卡片撑破 ——
* 这就是用户 2026-10-18 报的「左侧有空隙、右侧紧贴屏幕」。
* 原理:Row 里的子项默认 `min-width: auto`(= 按内容最小宽度),
* 长名字 / 多个标签会把这一行顶得比卡片可用宽度更宽;
* 卡片本身有 `margin(left/right: 16)`,但**布局盒被内容撑出去**,
* 于是右边越界贴到屏幕缘(左边因为 margin 先占位,所以还有空隙)。
* ⇒ 给两个可能变长的 Row 都开 `flexShrink(1)` + 给 Text 让路。
* (本项目第 N 次踩这个"flex 子项不收缩"的坑,见 pitfalls。) */
/* ⚠️ 允许收缩 —— 长名字不会把这一行顶出去。
* ⚠️ 注意:这**不是**"右侧贴屏幕"的根因(那个是卡片自己的
* `.width('100%')` + margin 打架,见下方卡片那段的说明);
* 它防的是"长名字把同行的小标签挤没"。 */
.flexShrink(1)
if (p.isAdmin) {
FbTag({ text: '管理员', tone: 'brand' })
@@ -1082,7 +1078,16 @@ export struct FbPeoplePage {
* 右侧撑破的元凶之一(固定宽度 + 不收缩)。
*/
}
.width('100%')
/* 🔴🔴 **绝对不要在这里写 `.width('100%')`**(2026-10-18 真机实测找到的真凶):
* 卡片同时有 `.margin({left:16, right:16})` 与 `.width('100%')` 时,
* `100%` 是相对**父容器全宽**(= 屏宽 1080),margin 再把盒子往右推
* ⇒ 实测卡片 x 范围是 `50 ~ 1080`(**左边留了 50、右边 0**),
* 正好就是用户报的「左侧有空隙、右侧紧贴屏幕」。
* ⇒ 去掉 `width`,Row 按"父宽 − margin"自适应,两边就都是 16。
* ⚠️ 一开始我误判成"内容把卡片撑破"(`flexShrink`),加了收缩也没用 ——
* 真正的证据是**布局树里卡片自己的 x 是 50~1080**(不是子节点越界)。
* 教训:先量**卡片本身**的盒子,再怀疑子节点。
*/
.padding({ left: 14, right: 14, top: 12, bottom: 12 })
/* 🔴 v59b(用户 2026-10-18):「每个人都是圆角矩形,往中间收一点,
* 距离左右都有点距离,每个人中间都有一点空隙。这样是很多个