FSA全栈行动 FSA全栈行动
首页
  • 移动端文章

    • Android
    • iOS
    • Flutter
  • 学习笔记

    • 《Kotlin快速入门进阶》笔记
    • 《Flutter从入门到实战》笔记
    • 《Flutter复习》笔记
前端
后端
  • 学习笔记

    • 《深入浅出设计模式Java版》笔记
  • 逆向
  • 分类
  • 标签
  • 归档
  • LinXunFeng
  • GitLqr

公众号:FSA全栈行动

记录学习过程中的知识
首页
  • 移动端文章

    • Android
    • iOS
    • Flutter
  • 学习笔记

    • 《Kotlin快速入门进阶》笔记
    • 《Flutter从入门到实战》笔记
    • 《Flutter复习》笔记
前端
后端
  • 学习笔记

    • 《深入浅出设计模式Java版》笔记
  • 逆向
  • 分类
  • 标签
  • 归档
  • LinXunFeng
  • GitLqr
  • AndroidUI

  • Android第三方SDK

  • Android混淆

  • Android仓库

  • Android新闻

  • Android系统开发

  • Android源码

  • Android注解AOP

  • Android脚本

  • AndroidTv开发

  • AndroidNDK

  • Android音视频

  • Android热修复

  • Android性能优化

  • Android云游戏

  • Android插件化

  • iOSUI

  • iOS工具

  • iOS底层原理与应用

  • iOS组件化

  • iOS音视频

  • iOS疑难杂症

  • iOS之Swift

  • iOS之RxSwift

  • iOS开源项目

  • iOS逆向

  • Flutter开发

    • Dart - 抽象类的实例化
    • Flutter - 打印好用的Debug日志
    • Flutter - 混合开发
    • Flutter - 解决混合开发iOS脚本打包遇到的问题
    • Flutter - 低版本在iOS14上遇到的问题与解决方案
    • Flutter - 解决原生弹窗的触摸事件被Flutter响应的问题
    • Flutter - 实现列表上下拉切换header
    • Flutter - 获取ListView当前正在显示的Widget信息
    • Flutter - 列表滚动定位超强辅助库,墙裂推荐!🔥
    • Flutter - 快速实现聊天会话列表的效果,完美💯
    • Flutter - 聊天输入框更新文本时的必备优化点🔖
    • Flutter - 我给官方提PR,解决run命令卡住问题 😃
    • Flutter - 探索run命令到底做了什么 🤔
    • Flutter - 引擎调试(iOS篇)🛠
    • Flutter - 引擎调试bug到提交PR实战 🐞
    • Flutter - 船新升级😱支持观察第三方构建的滚动视图💪
      • 一、概述
      • 二、自定义触发观察的时机
        • 1、autoTriggerObserveTypes 参数
        • 2、triggerOnObserveType 参数
      • 三、保持IM会话位置功能增强
      • 四、支持观察瀑布流
      • 五、支持观察viewport
      • 六、支持自定义观察对象和观察逻辑
        • 1、customTargetRenderSliverType 回调
        • 2、customHandleObserve 回调
        • 3、extendedHandleObserve 回调
      • 七、定位Tab的下标计算支持网格类型
    • Flutter - 瀑布流交替播放视频 🎞
    • Flutter - IM保持消息位置大升级(支持ChatGPT生成式消息) 🤖
    • Flutter - 滚动视图中的表单防遮挡 🗒
    • Flutter - 秒杀1/2曝光统计 📊
    • 一天内加入 Flutter 和 FlutterCandies 两大组织是什么体验 🧐
    • Flutter - 如何快速搓一个微信通讯录列表(azlist) 📓
    • Flutter - 混编项目集成Shorebird热更新🐦(安卓篇)
    • Flutter - 混编项目集成Shorebird热更新🐦(iOS篇)
    • Flutter - 解决返回原生页面时dispose方法未被触发的问题 🐞
    • Flutter - 升级3.19之后页面多次rebuild?🤨
    • Flutter - 热更新 Shorebird 1.0 正式版来了 🐦
    • Flutter - 使用Pigeon实现视频缓存插件 🐌
    • Flutter - 轻松搞定屏幕旋转功能 😎
    • Flutter - 解决Connection closed before full header was received
    • Flutter - 实现聊天键盘与功能面板的丝滑切换 🍻
    • Flutter - 支持观察NestedScrollView,兼容性更强 😈
    • Flutter - 聊天键盘与面板丝滑切换的强势升级 🍻
    • Flutter - 升级到3.24后页面还会多次rebuild吗?🧐
    • Flutter - 轻松实现PageView卡片偏移效果
    • Flutter - 轻松搞定炫酷视差(Parallax)效果
    • Flutter - 危!3.24版本苹果审核被拒!
    • Flutter - 子部件任意位置观察滚动数据
    • Flutter - iOS编译加速
    • Flutter - Xcode16 还原编译速度
  • 移动端
  • Flutter开发
LinXunFeng
2023-06-04
目录

Flutter - 船新升级😱支持观察第三方构建的滚动视图💪

欢迎关注微信公众号:[FSA全栈行动 👋]

# 一、概述

感谢大家对 scrollview_observer (opens new window) 的支持,上一篇关于 scrollview_observer (opens new window) 的最新一篇文章是在2022年的10月份,不知不觉已经过去了8个月,它现在已经变得更加完善和强大,让我们一起来看看都做了哪些更新吧 🥳

版本信息

  • 当前版本: 1.13.2
  • GitHub地址: https://github.com/LinXunFeng/flutter_scrollview_observer (opens new window)

# 二、自定义触发观察的时机

未添加该功能前,滚动视图在整个滚动过程中都会被观察,计算找出第一个 item 和正在展示的所有 item,当第一个 item 或者正在展示的 item 的对象发生变化时才会调用 [onObserve] 和 [onObserveAll] 回调。

但往往在一些场景下,我们想要指定在某个滚动状态下才进行观察,以及观察回调的触发时机,那该怎么办呢?

# 1、autoTriggerObserveTypes 参数

现在你可以通过该参数设置自动触发观察的时机,定义如下:

final List<ObserverAutoTriggerObserveType>? autoTriggerObserveTypes;
enum ObserverAutoTriggerObserveType {
  scrollStart,
  scrollUpdate,
  scrollEnd,
}

其默认值为 [.scrollStart, .scrollUpdate, .scrollEnd]

枚举值说明:

枚举值 描述
scrollStart 开始滚动
scrollUpdate 滚动中
scrollEnd 结束滚动

如在视频列表的场景中,我们可能只需要在列表结束滚动时再去做观察哪个 item 是第一个,然后进行自动播放,这个时候设置 autoTriggerObserveTypes 为 .scrollEnd 即可,同时也避免了大量不必要的计算。

# 2、triggerOnObserveType 参数

用于配置触发 [onObserve] 和 [onObserveAll] 回调的前提,定义如下:

final ObserverTriggerOnObserveType triggerOnObserveType;
enum ObserverTriggerOnObserveType {
  directly,
  displayingItemsChange,
}

其默认值为 .displayingItemsChange

枚举值说明:

枚举值 描述
directly 观察到数据后直接将数据返出
displayingItemsChange 当列表子部件进出或数量发生变化时将观察到的数据返出

一般是在实时获取 item 的 leadingMarginToViewport(item 顶部与视窗顶部的距离) 和 trailingMarginToViewport(item 底部与视窗底部的距离)的时候比较常用。

# 三、保持IM会话位置功能增强

之前限制只支持插入一条消息时保持会话位置,现在放开支持多条,使用方式不变,效果如下

注:该功能依赖被插入消息前的最新消息视图做为参照去计算偏移量,所以如果一次性插入的消息数太多,导致该参照消息视图无法得到渲染,则该功能会失效,需要你自己去对 ScrollView 的 cacheExtent 设置合理的值来尽量避免这个问题!

# 四、支持观察瀑布流

原先仅针对 GridView 这种常规网格布局,只处理顶部偏移量一致的 item,现在调整了内部处理逻辑,已支持瀑布流这种模式

如上图红线所示,位于第一的 item 是 grid item2 和 grid item3。

# 五、支持观察viewport

大家多多少少会遇到这种情况,在 CustomScrollView 中放置了好多 sliver,需要对它们进行观察,判断哪些 sliver 正在展示,而不仅仅是观察 SliverList 和 SliverGrid 中的 item。

在这里可以使用 onObserveViewport 回调得到你想要的结果,代码如下

SliverViewObserver(
  child: _buildScrollView(),
  sliverContexts: () {
    return [
      if (grid1Context != null) grid1Context!,
      if (swipeContext != null) swipeContext!,
      if (grid2Context != null) grid2Context!,
    ];
  },
  onObserveViewport: (result) {
    firstChildCtxInViewport = result.firstChild.sliverContext;
    if (firstChildCtxInViewport == grid1Context) {
      debugPrint('current first sliver in viewport - gridView1');
    } else if (firstChildCtxInViewport == swipeContext) {
      debugPrint('current first sliver in viewport - swipeView');
    } else if (firstChildCtxInViewport == grid2Context) {
      debugPrint('current first sliver in viewport - gridView2');
    }
  },
)
  1. 在 sliverContexts 回调中返回需要观察的 sliver 的 BuildContext。
  2. 在 onObserveViewport 回调中拿到观察结果,结果对应的类为 SliverViewportObserveModel
class SliverViewportObserveModel {
  /// 当前 CustomScrollView 所对应的 viewport 实例.
  final RenderViewportBase viewport;

  /// 根据 sliverContexts,返回当前观察到的第一个 sliver
  final SliverViewportObserveDisplayingChildModel firstChild;

  /// 根据 sliverContexts,返回当前观察到的正在展示的所有 sliver
  final List<SliverViewportObserveDisplayingChildModel>
      displayingChildModelList;
  ...
}

这里需要注意的是,观察的对象不应为嵌套的 sliver,如下代码所示:

SliverPadding(
  sliver: SliverList(
    delegate: SliverChildBuilderDelegate(
      (context, index) {
        return ListTile(title: Text('index - $index'));
      },
    ),
  ),
  padding: const EdgeInsets.all(8),
);

你需要观察的是 SliverPadding,而不是 SliverList,在给 sliverContexts 传递数据时需要留意,否则观察无效。

那一块的 Sliver 的 BuildContext 要怎么获取?

你可以使用 GlobalKey,但这里更建议使用 SliverLayoutBuilder

SliverLayoutBuilder(
  builder: (context, _) {
    // 将 context 记录起来
    if (sliverCtx != context) sliverCtx = context;
  
    SliverPadding(
      sliver: SliverList(
        delegate: SliverChildBuilderDelegate(
          ...
        ),
      ),
      padding: const EdgeInsets.all(8),
    );
  },
);

# 六、支持自定义观察对象和观察逻辑

# 1、customTargetRenderSliverType 回调

仅支持 ListViewObserver 和 GridViewObserver

在保持原来的观察逻辑上,告诉 scrollview_observer 要处理的 RenderSliver 类型,目的是为了支持对第三方库构建的滚动视图进行观察。

customTargetRenderSliverType: (renderObj) {
  // 告诉该库它需要观察什么类型的 RenderObject
  // 这里以观察 loading_more_list 的 ListView 为例
  return renderObj is ExtendedRenderSliverList;
},

这里罗列几个在 loading_more_list 中常用的 RenderObject 供大家对照使用。

类型 RenderObject
ListView ExtendedRenderSliverList
GridView ExtendedRenderSliverGrid
WaterfallFlow RenderSliverWaterfallFlow

# 2、customHandleObserve 回调

该回调用于自定义观察逻辑,当自带的处理逻辑不符合你的需求时使用。

customHandleObserve: (context) {
  // 可以完全自定义你的观察逻辑
  final _obj = context.findRenderObject();
  if (_obj is RenderSliverList) {
    // 可以使用该库提供的默认处理方式
    ObserverCore.handleListObserve(context: context);
  }
  if (_obj is RenderSliverGrid || _obj is RenderSliverWaterfallFlow) {
    // 可以使用该库提供的默认处理方式
    return ObserverCore.handleGridObserve(context: context);
  }
  // 处理一些由第三方构建的 Sliver
  ...
  
  // 其它类型不做处理
  return null;
},

现已将原处理 RenderSliverList 和 RenderSliverGride 的逻辑抽离至 ObserverCore 中供大家自由组合使用。

# 3、extendedHandleObserve 回调

仅支持 SliverViewObserver

该回调用于对原来的观察逻辑进行补充,原来只处理 RenderSliverList、RenderSliverFixedExtentList 和 RenderSliverGrid。

extendedHandleObserve: (context) {
  // 在对原来的观察逻辑进行拓展
  final _obj = context.findRenderObject();
  if (_obj is RenderSliverWaterfallFlow) {
    return ObserverCore.handleGridObserve(context: context);
  }
  return null;
},

结合 ObserverCore 和以上的几个功能点,实现了可自由观察由第三方构建的滚动视图的功能,不再局限于官方的 SliverList 和 SliverGrid。

这是一个很有用的功能,它让你的滚动视图的构建变得更加自由,比如观察使用 fluttercandies/waterfall_flow (opens new window) 构建的瀑布流。

# 七、定位Tab的下标计算支持网格类型

对 ObserverUtils.calcAnchorTabIndex 进行增强,现支持处理列表和网格的模块下标计算,这里直接看效果图

GitHub: https://github.com/LinXunFeng/flutter_scrollview_observer (opens new window)

#Dart#Flutter
Flutter - 引擎调试bug到提交PR实战 🐞
Flutter - 瀑布流交替播放视频 🎞

← Flutter - 引擎调试bug到提交PR实战 🐞 Flutter - 瀑布流交替播放视频 🎞→

最近更新
01
Flutter - Xcode16 还原编译速度
04-05
02
AI - 免费的 Cursor 平替方案
03-30
03
Android - 2025年安卓真的闭源了吗
03-28
更多文章>
Theme by Vdoing | Copyright © 2020-2025 FSA全栈行动
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×