一、痛点
痛点一:flutter 官方提供了 scrollcontroller,调用下方两个方法可以滚动到指定偏移处
void jumpto(double value)
future<void> animateto(
double offset, {
required duration duration,
required curve curve,
})
但是官方没有提供滚动到指定下标位置的功能
痛点二:
为了解决痛点一,业内有很多第三方库实现了这个功能,其中最知名的莫过于谷歌的 scrollable_positioned_list
而这些库都有一些相同的问题:
- 侵入性强,必须使用他们提供的
widget来构建列表视图 - 不支持
gridview
对此,我决定自己编写一个库(flutter_scrollview_observer)来实现这个功能,以及解决以上的问题。
二、优点
- 侵入性低,不会限制你的列表视图实现,只要求将列表视图做为
viewobserver的child,如果不想用了,直接移除掉viewobserver即可。 - 基于【不会限制你的列表视图实现】这一点,
flutter_scrollview_observer支持所有的列表widget,如:listview、gridview,甚至customsrollview - 防抖动,如果在滚动到指定下标时,列表尾部的可滚动区域已不足以支撑滚动到相应位置,则会自动滚动到最底部,避免回弹的问题
下面正式介绍一下这个库的使用
三、使用
1、listview
正常创建和使用 scrollcontroller 实例
这里你可以使用 listview 或者 customsrollview 的 sliverlist
scrollcontroller scrollcontroller = scrollcontroller();
listview _buildlistview() {
return listview.separated(
controller: scrollcontroller,
...
);
}
创建 listobservercontroller 实例并将其传递给 listviewobserver
listobservercontroller observercontroller = listobservercontroller(controller: scrollcontroller); listviewobserver( controller: observercontroller, child: _buildlistview(), ... )
注意:创建 listobservercontroller 实例时需要传入列表的 scrollcontroller 实例。 这一步很重要,因为 flutter_scrollview_observer 内部实现原理是基于官方 scrollcontroller 提供的 jumpto 和 animateto 方法
现在即可滚动到指定下标位置了
// 无动画滚动至下标位置 observercontroller.jumpto(index: 100) // 动画滚动至下标位置 observercontroller.animateto( index: 100, duration: const duration(seconds: 1), curve: curves.ease, );

2、gridview
内容与 listview 基本一致


正常创建和使用 scrollcontroller 实例
widget _buildgridview() {
return gridview.builder(
...
controller: scrollcontroller,
...
);
}
创建 gridobservercontroller 实例并将其传递给 gridviewobserver
gridobservercontroller observercontroller = gridobservercontroller(controller: scrollcontroller); gridviewobserver( controller: observercontroller, child: _buildgridview(), )
现在即可滚动到指定下标位置了
observercontroller.jumpto( index: 40, ); observercontroller.animateto( index: 40, duration: const duration(seconds: 1), curve: curves.ease, );
3、customsrollview
支持 sliverlist 和 slivergrid 混合使用的情况!

如上图所示,customsrollview 的 slivers 中包含有 sliverlist 和 slivergrid
- 点击右下角第一个按钮可滚动到
sliverlist的第29行 - 点击第二个按钮可滚动到
slivergrid的第10的子部件所在行
正常创建和使用 scrollcontroller 实例
widget _buildscrollview() {
return customscrollview(
controller: scrollcontroller,
// scrolldirection: axis.horizontal,
slivers: [
_buildsliverlistview(),
_buildslivergridview(),
],
);
}
正常创建你的 sliverlist 和 slivergrid,并将它们的 buildcontext 记录起来
widget _buildsliverlistview() {
return sliverlist(
delegate: sliverchildbuilderdelegate(
(ctx, index) {
_sliverlistctx ??= ctx;
...
},
...
),
);
}
widget _buildslivergridview() {
return slivergrid(
...
delegate: sliverchildbuilderdelegate(
(buildcontext context, int index) {
_slivergridctx ??= context;
...
},
...
),
);
}
创建 sliverobservercontroller 实例并将其传递给 sliverviewobserver
注意:在 sliverlistcontexts 里返回刚才记录的两个 sliver 的 buildcontext
sliverobservercontroller observercontroller = sliverobservercontroller(controller: scrollcontroller);
sliverviewobserver(
controller: observercontroller,
child: _buildscrollview(),
sliverlistcontexts: () {
return [
if (_sliverlistctx != null) _sliverlistctx!,
if (_slivergridctx != null) _slivergridctx!,
];
},
...
),
现在即可滚动到指定下标位置了
observercontroller.animateto( slivercontext: _sliverlistctx, index: 29, duration: const duration(milliseconds: 300), curve: curves.easeinout, ); observercontroller.animateto( slivercontext: _slivergridctx, index: 10, duration: const duration(milliseconds: 300), curve: curves.easeinout, );
四、说明
1、viewobserver 的选择
建议使用相应的 viewobserver:
- 如果是
listview或者纯sliverlist,建议使用listviewobserver - 如果是
gridview或者纯slivergrid,建议使用gridviewobserver - 如果是
sliverlist和slivergrid,则使用sliverviewobserver
这样在 onobserve 回调中拿到数据模型后不用再对其进行类型判断与转换。
2、isfixedheight
子部件为固定高度的情况下,请设置 isfixedheight 为 true,以提升性能!
observercontroller.jumpto( index: 100, isfixedheight: true ); observercontroller.animateto( index: 100, isfixedheight: true, duration: const duration(seconds: 1), curve: curves.ease, );
3、slivercontext 是否需要传
jumpto({
required int index,
buildcontext? slivercontext,
bool isfixedheight = false,
})
animateto({
required int index,
required duration duration,
required curve curve,
buildcontext? slivercontext,
bool isfixedheight = false,
})
如上,jumpto 和 animateto 方法中都有一个 slivercontext 参数,这是用来指定哪个 sliver 进行滚动操作的。
如果不传 slivercontext,则默认会是列表中的第一个 sliver,只有你想让非第一个 sliver 进行滚动的时候才需要传该值
五、可现实的功能
1、获得当前视窗中的子部件信息

如上图控制台所示,在滚动的过程中可以实时获取正在显示的子部件的数据。
2、视频列表自动播放

这种功能很常见,在列表滚动的时候,指定区域内的被命中的视频便会自动进行播放。
3、模块定位

一般详情页中都会有的功能,在列表视图滚动的时候,顶部定位导航视图跟着更新下标,点击导航视图某个下标则会定位到对应的模块
六、最后
如果这个库对你很有帮助,请不吝给个 star 吧
github: flutter_scrollview_observer
以上就是flutter列表滚动定位超强辅助库使用示例详解的详细内容,更多关于flutter列表滚动定位辅助库的资料请关注代码网其它相关文章!
发表评论