npx skills add ...
npx skills add tencent-tds/kuiklyui-ai --skill kuikly-visibility-exposure
Kuikly 曝光与可见性事件开发助手(Kuikly DSL)。指导如何使用 didAppear、didDisappear、willAppear、willDisappear、appearPercentage 五种可见性事件实现组件曝光上报、可见百分比监听、列表项曝光统计等功能。当用户在 Kuikly 中需要实现曝光上报、可见性监听、列表项曝光统计、可见百分比计算等场景时使用。
npx skills add tencent-tds/kuiklyui-ai --skill kuikly-visibility-exposure
Kuikly 提供了一套完整的组件可见性事件系统,用于监听组件在滚动容器或页面中的可见状态变化。四大要素:
系统从组件的 parent 开始向上遍历,找到第一个匹配的祖先作为可见窗口:
重要:可见性是相对于最近滚动容器的可见区域,而非屏幕位置。若需屏幕位置可见性,如果嵌套滚动容器场景,可使用外层滚动容器的 scroll 事件回调,结合列表偏移量计算节点真实位置。
三种空间关系与状态转换:
| 空间关系 | 判定条件 | 状态转换 |
|---|---|---|
| 相离(组件完全在窗口外) | 组件 frame 与窗口无交集 | → WILL_DISAPPEAR → DID_DISAPPEAR |
| 包含(组件完全在窗口内) | 组件 frame 完全在窗口内 | → WILL_APPEAR → DID_APPEAR |
| 相交(组件部分在窗口内) | 组件 frame 与窗口部分重叠 | 从 DID_DISAPPEAR → WILL_APPEAR;从 DID_APPEAR → WILL_DISAPPEAR |
特殊行为:
addNextTickTask 调度),页面销毁时除外(同步执行)| 事件 | 描述 | 回调参数 | import |
|---|---|---|---|
willAppear { } | 组件将要可见(部分进入窗口) | 无 | com.tencent.kuikly.core.base.event.willAppear |
didAppear { } | 组件完全可见(完全在窗口内) | 无 | com.tencent.kuikly.core.base.event.didAppear |
willDisappear { } | 组件将要不可见(部分离开窗口) | 无 | com.tencent.kuikly.core.base.event.willDisappear |
didDisappear { } | 组件完全不可见(完全在窗口外) | 无 | com.tencent.kuikly.core.base.event.didDisappear |
appearPercentage { } | 组件可见百分比变化 | percentage01: Float([0,1]) | com.tencent.kuikly.core.base.event.appearPercentage |
| 空间关系 | percentage 值 |
|---|---|
| 完全不可见(相离) | 0 |
| 完全可见(包含) | 1 |
| 部分可见(相交) | 纵向列表:可见高度 / 组件高度;横向列表(FlexDirection.ROW / ROW_REVERSE):可见宽度 / 组件宽度 |
percentage 值始终被 clamp 到 [0, 1] 范围内。只有当 percentage 发生变化时才会触发回调。
| 属性 | 描述 | 参数类型 | 支持的容器 |
|---|---|---|---|
visibleAreaIgnoreTopMargin(margin) | 从可见窗口顶部裁掉指定高度 | Float | Scroller、List、WaterfallList |
visibleAreaIgnoreBottomMargin(margin) | 从可见窗口底部裁掉指定高度 | Float | Scroller、List、WaterfallList |
作用原理:缩小列表的"可见性判定窗口"。设置后,可见窗口高度 = 列表高度 - marginTop - marginBottom,子组件 Y 坐标也会减去 marginTop。例如列表高度 500dp,设置
visibleAreaIgnoreTopMargin(60f)和visibleAreaIgnoreBottomMargin(80f)后,只有列表中间 360dp 区域内的子组件才会被判定为可见。典型场景:列表顶部/底部有固定遮挡 UI(如悬浮导航栏、半透明蒙层、底部工具栏),被遮挡区域内的子组件虽然在列表坐标系内"可见",但实际上用户看不到,需要从曝光判定中排除。
| 错误做法 | 正确做法 | 原因 |
|---|---|---|
❌ 根节点使用 didAppear 监听页面曝光 | ✅ 使用页面生命周期 pageDidAppear() | 根节点没有滚动容器作为可见窗口,行为不可预期 |
| ❌ 认为可见性是相对于屏幕位置 | ✅ 可见性是相对于最近滚动容器的可见区域 | 需要屏幕位置请结合 scroll 事件偏移量计算 |
❌ 在 appearPercentage 中直接执行曝光上报 | ✅ 曝光上报用 didAppear,或加阈值 + 去重标记 | appearPercentage 每次滚动都触发,频率极高 |
| ❌ 忘记 import 可见性事件扩展函数 | ✅ 添加对应的 import 语句 | 这些是 Event 的扩展函数,需要显式 import |
import com.tencent.kuikly.core.base.event.didAppear
View {
attr {
size(100f, 100f)
backgroundColor(Color.GREEN)
}
event {
didAppear {
// 组件完全可见,执行曝光上报
}
}
}import com.tencent.kuikly.core.base.event.appearPercentage
View {
attr {
size(100f, 100f)
backgroundColor(Color.GREEN)
}
event {
appearPercentage { percentage01 ->
// percentage01 为 [0,1] 的露出百分比
// 1 表示 100% 可见,0 表示 0% 可见
if (percentage01 >= 0.5f) {
// 超过 50% 可见时执行逻辑
}
}
}
}import com.tencent.kuikly.core.base.event.willAppear
import com.tencent.kuikly.core.base.event.didAppear
import com.tencent.kuikly.core.base.event.willDisappear
import com.tencent.kuikly.core.base.event.didDisappear
import com.tencent.kuikly.core.base.event.appearPercentage
View {
event {
willAppear {
// 组件将要可见(部分进入窗口)
}
didAppear {
// 组件完全可见 → 曝光上报
}
willDisappear {
// 组件将要不可见(部分离开窗口)
}
didDisappear {
// 组件完全不可见
}
appearPercentage { percentage ->
// 可见百分比变化
}
}
}import com.tencent.kuikly.core.base.event.didAppear
Scroller {
attr {
flex(1f)
// 顶部 60dp 区域内的子组件不参与曝光判定
visibleAreaIgnoreTopMargin(60f)
// 底部 80dp 区域内的子组件不参与曝光判定
visibleAreaIgnoreBottomMargin(80f)
}
View {
attr {
height(120f)
backgroundColor(Color(0xFFE3F2FD))
}
event {
didAppear {
// 只有完全进入中间有效区域(500 - 60 - 80 = 360dp)时才触发
}
}
}
}