Flutter 各种列表曝光方案
目前的曝光有两大场景:播放器可视播放和元素曝光
其中元素曝光还需要细分,有主轴方向滑动曝光,还有混合纵轴方向滑动曝光
场景一:滑动中可视元素内选取元素播放或者停止播放
场景特点
需要在滑动中获取当前可视元素和移除可视范围的元素
- 先判断移除移除可视的元素是否存在播放,如果有,停止播放。
- 在上一步执行完毕之后,判断新的可视元素中是否含符合播放标准
- 开启下一轮播放
- 播放结束前没有被划走,继续监测其他符合播放的元素播放
曝光特点
- 实时监听滑动中视口内元素变化
- 在监听回调中需要同时拿到当前所有可视元素,进行规则匹配
技术方案
API
1 | /// The callback of getting observed result map. |
sliverListContexts
如果不为null,列表会通过element.visitChildren
方法获取的sliverlist列表。
onObserveAll
:是返回所有sliverlist回调
注意:
onObserveAll
返回所有sliverlist
,并不能一一绑定。需要通过函数返回的Map实例的key进行查找。
onObserve
:是返回第一个sliverlist回调
场景二:可视曝光
元素进入屏幕视口内回调,一般用于曝光打点
场景特点
- 用于列表元素曝光打点
曝光特点
- 每次曝光处理,元素独自处理,和列表其他元素曝光没有耦合。
技术方案
ScrollDetailProvider
嵌套滑动列表,监听滑动通知并根据需求转化通知到子组件Exposure
嵌套需要统计的单个元素,Exposure
接受ScrollDetailProvider
转化的通知,根据自身的偏移量判断是否在视口内。ExposureController
实例可以绑定多个Exposure
,通过调用reCheckExposeState
方法手动获取一遍当前视口曝光情况
场景三:可视曝光——特殊组合
我们在监测主轴曝光的同时,对特殊元素需要监测纵轴方向曝光。
场景特点
- 曝光列表中特殊元素曝光
- 适用于任何
renderObject
曝光特点
- 每次曝光处理,元素独自处理,和列表其他元素曝光没有耦合。
技术方案
visibility_detector
个人认为效率不高,而且回调次数较多。
需要监听的组件通过该三方组件直接嵌套
监听
onVisibilityChanged
回调,通过可视比例判断是否满足曝光在元素paint的方法中调用元素(PaintingContext)的
addCompositionCallback
方法,在上述方法中,调用计算任务去判断可视比例
计算任务,通过获取父级列表(到顶端),通过
rect
和transform
计算当前元素的bounds
,组合成VisibilityInfo
1
2
3
4
5final List<ContainerLayer> ancestors = <ContainerLayer>[ContainerLayer()];
while (ancestor != null && ancestor.parent != null) {
ancestors.add(ancestor);
ancestor = ancestor.parent;
}VisibilityInfo
中有visibleBounds
——实际可视的区域,visibleFraction
——显示比例