地址联想框选中后重复弹出、位置翻到下方;电影弹层无法滚动 #54

Open
opened 2026-11-05 04:40:44 +00:00 by laoyang · 0 comments
Owner

地址联想框重复弹出、位置跑到下方;电影弹层无法滚动

一、地址联想框选中后又弹一次

「点击地址,出现后,选中,又会弹出一次地址选择框,就是那个联想框,
这个在添加日程时就有,这次又出现了。这个并没有解决。」

前三次都没修好(都靠"比字符串")

版本 做法 为什么失败
1 lastApplied 原串比对 回写可能带空格差异
2 加 primed 只防首次挂载 防不住选中后的回写
3 trim() 比对 ArkUI 触发多次 onChange 且值有微妙差异,仍漏

真因

值比对这条路本身不可靠。 ArkUI 在 TextInput 内容被程序改写时,
onChange 的触发次数和时机不确定(重渲染一次、光标定位一次、输入法同步一次)。
只要有一次值与 lastApplied 不一致,就会搜一次,框就重弹。

修法:时间窗抑制

// pick() 里
this.suppressUntil = Date.now() + 600;

// onType() 最开头
if (Date.now() < this.suppressUntil) { return; }

600ms 内任何 onChange 都直接返回,不管触发几次、值有无差异。

⚠️ 不担心误伤真实输入:人不可能在 600ms 内打完第二个字
(正常打字间隔 150~300ms,且刚点完候选视线还在候选框上)。
即便真打了,防抖 260ms 后仍会搜一次,只是"慢半拍"。

⚠️ 与值比对并存(时间窗兜住"刚选中"瞬间,值比对兜住"稍后回写")。

二、联想框位置跑到输入框下方

「有时候弹出的框会在输入框下面。我们之前定的是在输入框上面弹出来,
不然如果在下面弹出来,会被输入键盘挡住。」

真因

bindPopup 的 placement: Placement.Top 只是偏好,
上方空间不足时系统会自动翻到下方。没有"强制在上"的开关。

修法

让它在上方放得下:候选列表 maxHeight 从 220 收到 180,
更容易塞进上方空间。

三、电影弹层划不动

「"记一场电影"这种输入,输入框怎么上下划不动?」

真因

Scroll() { ... }
  .flexShrink(1)      // ← 只是"允许被压缩"
  .width('100%')

在 Column 里,Scroll 需要 layoutWeight(1) 才能拿到"剩余高度"。
只写 flexShrink(1) 时,Scroll 高度 = 内容高度(超出父级后被裁切)
⇒ 自身没有可滚动空间 ⇒ 划不动。

修法

.layoutWeight(1)
.edgeEffect(EdgeEffect.Spring)

改动清单

文件 改动
FbAddrInput.ets 时间窗 suppressUntil;候选限高 180
FbMovieNewSheet.ets Scroll 改 layoutWeight(1)

验收

  • 选完地址候选后 600ms 内不再弹
  • 联想框尽量在上方弹出
  • 「记一场电影」能上下滑动

遗留

Placement.Top 只是偏好这点无法从端上强制。
若仍频繁翻到下方,需改成内联在 Scroll 流内或自定义全屏浮层。


为什么单独建单

#51 里有「端上地址拿详细地址」,但那是数据结构问题(onPick 回调);本单是交互问题(选中后重弹、弹窗位置、滚动失效)。两者在同一个组件里但根因完全不同。

# 地址联想框重复弹出、位置跑到下方;电影弹层无法滚动 ## 一、地址联想框选中后又弹一次 > 「点击地址,出现后,选中,又会弹出一次地址选择框,就是那个联想框, > 这个在添加日程时就有,这次又出现了。这个并没有解决。」 ### 前三次都没修好(都靠"比字符串") | 版本 | 做法 | 为什么失败 | |---|---|---| | 1 | `lastApplied` 原串比对 | 回写可能带空格差异 | | 2 | 加 `primed` 只防首次挂载 | 防不住选中后的回写 | | 3 | `trim()` 比对 | ArkUI 触发**多次** onChange 且值有微妙差异,仍漏 | ### 真因 **值比对这条路本身不可靠。** ArkUI 在 TextInput 内容被程序改写时, onChange 的**触发次数和时机不确定**(重渲染一次、光标定位一次、输入法同步一次)。 只要有一次值与 `lastApplied` 不一致,就会搜一次,框就重弹。 ### 修法:时间窗抑制 ```typescript // pick() 里 this.suppressUntil = Date.now() + 600; // onType() 最开头 if (Date.now() < this.suppressUntil) { return; } ``` 600ms 内**任何** onChange 都直接返回,不管触发几次、值有无差异。 ⚠️ 不担心误伤真实输入:人不可能在 600ms 内打完第二个字 (正常打字间隔 150~300ms,且刚点完候选视线还在候选框上)。 即便真打了,防抖 260ms 后仍会搜一次,只是"慢半拍"。 ⚠️ 与值比对**并存**(时间窗兜住"刚选中"瞬间,值比对兜住"稍后回写")。 ## 二、联想框位置跑到输入框下方 > 「有时候弹出的框会在输入框下面。我们之前定的是在输入框上面弹出来, > 不然如果在下面弹出来,会被输入键盘挡住。」 ### 真因 `bindPopup` 的 `placement: Placement.Top` 只是**偏好**, 上方空间不足时系统会自动翻到下方。**没有"强制在上"的开关。** ### 修法 让它在上方**放得下**:候选列表 `maxHeight` 从 220 收到 **180**, 更容易塞进上方空间。 ## 三、电影弹层划不动 > 「"记一场电影"这种输入,输入框怎么上下划不动?」 ### 真因 ```typescript Scroll() { ... } .flexShrink(1) // ← 只是"允许被压缩" .width('100%') ``` 在 `Column` 里,`Scroll` 需要 **`layoutWeight(1)`** 才能拿到"剩余高度"。 只写 `flexShrink(1)` 时,Scroll 高度 = 内容高度(超出父级后被裁切) ⇒ 自身没有可滚动空间 ⇒ **划不动**。 ### 修法 ```typescript .layoutWeight(1) .edgeEffect(EdgeEffect.Spring) ``` ## 改动清单 | 文件 | 改动 | |---|---| | `FbAddrInput.ets` | 时间窗 `suppressUntil`;候选限高 180 | | `FbMovieNewSheet.ets` | Scroll 改 `layoutWeight(1)` | ## 验收 - [ ] 选完地址候选后 600ms 内不再弹 - [ ] 联想框尽量在上方弹出 - [ ] 「记一场电影」能上下滑动 ## 遗留 `Placement.Top` 只是偏好这点无法从端上强制。 若仍频繁翻到下方,需改成**内联在 Scroll 流内**或自定义全屏浮层。 --- ### 为什么单独建单 #51 里有「端上地址拿详细地址」,但那是数据结构问题(onPick 回调);本单是交互问题(选中后重弹、弹窗位置、滚动失效)。两者在同一个组件里但根因完全不同。
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/FamilyBook#54