Flutter滚动位置监听插件positioned_scroll_observer的使用
Flutter滚动位置监听插件 positioned_scroll_observer
的使用
positioned_scroll_observer
是一个用于监听和控制滚动位置的Flutter插件。它支持多种滚动视图(如 ListView
, GridView
, SingleChildScrollView
等),并提供了丰富的功能,例如根据索引跳转、动画到特定位置、检查元素是否可见等。
主要特性
- 根据索引跳转或动画到指定位置:使用
jumpToIndex
和animateToIndex
方法。 - 按比例跳转或动画到视口中的位置:适用于快速跳转到列表的顶部、中间或底部。
- 保留旧的滚动偏移量:使用
PositionRetainedScrollPhysics
避免在顶部添加新项目时滚动位置发生变化。 - 检查特定索引是否在屏幕上可见。
- 获取当前视口中可见的所有项目。
- 检查特定
RenderObject
在视口中的可见比例。
使用步骤
1. 创建并绑定观察者
首先需要创建一个观察者,并将其绑定到所有子项上。可以通过 ObserverProxy
来包裹每个子项。
2. 使用观察者
_observer.jumpToIndex(
index,
position: _controller.position,
);
_observer.animateToIndex(
index,
position: _controller.position,
duration: const Duration(milliseconds: 200),
curve: Curves.fastLinearToSlowEaseIn,
);
示例代码
示例1:单ChildScrollView 和 ListWheelScrollView
创建观察者
final ScrollController _controller = ScrollController();
late final _observer = ScrollObserver.boxMulti(
axis: Axis.vertical, // 指定滚动方向
itemCount: 30, // 子项数量
);
绑定观察者到子项
SingleChildScrollView(
controller: _controller,
scrollDirection: Axis.vertical,
child: Column(
children: [
for (int i = 0; i < 30; i++)
ObserverProxy(
observer: _observer,
child: DecoratedBox(
decoration: BoxDecoration(border: Border.all()),
child: SizedBox(
height: 100,
width: 100,
child: Center(
child: Text("Column item $i"),
),
),
),
),
],
),
);
示例2:SliverWidgets (如 ListView
, GridView
)
创建观察者
final ScrollController _controller = ScrollController();
late final _observer = ScrollObserver.sliverMulti(itemCount: 30);
绑定观察者到子项
ListView.builder(
controller: _controller,
itemBuilder: (context, index) => ObserverProxy(
observer: _observer,
child: ListTile(
key: ValueKey<int>(index),
leading: const CircleAvatar(
child: Text("L"),
),
title: Text("Positioned List Example $index"),
),
),
itemCount: 30,
);
示例3:自定义滚动视图
对于 ListView.custom
和 GridView.custom
,可以使用 PositionedChildListDelegate
和 PositionedChildBuilderDelegate
方便地包裹子项:
ListView.custom(
controller: _controller,
childrenDelegate: PositionedChildBuilderDelegate(
builder: (context, index) {
return ObserverProxy(
observer: _observer,
child: ListTile(
title: Text("Custom ListView Item $index"),
),
);
},
childCount: 30,
),
);
更多功能
检查索引是否可见
bool isVisible = _observer.isRevealed(index);
获取当前视口中的可见项
List<int> visibleItems = _observer.getVisibleIndexes();
保持滚动偏移量
当在顶部添加新项目时,避免滚动位置发生变化:
ListView.builder(
controller: _controller,
reverse: true,
physics: const PositionRetainedScrollPhysics(),
itemBuilder: (context, index) => _items[index],
itemCount: _itemCount,
);
按比例跳转或动画到视口中的位置
_observer.showInViewport(
_controller.position,
alignment: 0.5, // 0.0 表示对齐到视口的开头,0.5 表示居中,1.0 表示对齐到末尾
);
注意事项
- 所有子项必须用
ObserverProxy
包裹。 - 观察者的
itemCount
必须与实际子项数量一致。 - 当使用
ScrollObserver.boxMulti
时,必须指定axis
参数。
完整示例 Demo
以下是一个完整的示例,展示了如何使用 positioned_scroll_observer
插件来实现滚动监听和控制:
import 'package:flutter/material.dart';
import 'package:positioned_scroll_observer/positioned_scroll_observer.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Scroll Observer Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late final ScrollController _controller;
late final ScrollObserver _observer;
@override
void initState() {
super.initState();
_controller = ScrollController();
_observer = ScrollObserver.sliverMulti(itemCount: 30);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView.builder(
controller: _controller,
itemBuilder: (context, index) => ObserverProxy(
observer: _observer,
child: ListTile(
title: Text("Item $index"),
),
),
itemCount: 30,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_observer.animateToIndex(15, position: _controller.position, duration: Duration(seconds: 1));
},
tooltip: 'Jump to Index 15',
child: Icon(Icons.arrow_downward),
),
);
}
}
这个示例展示了如何使用 positioned_scroll_observer
插件来监听和控制滚动位置,并通过按钮点击将滚动位置动画到第15个子项。
更多关于Flutter滚动位置监听插件positioned_scroll_observer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复