对于滚动的视图,我们经常需要监听它的一些滚动事件,在监听到的时候去做对应的一些事情。
比如视图滚动到底部时,我们可能希望做上拉加载更多;
比如滚动到一定位置时显示一个回到顶部的按钮,点击回到顶部的按钮,回到顶部;
比如监听滚动什么时候开始,什么时候结束;
在Flutter中监听滚动相关的内容由两部分组成:ScrollController和ScrollNotification。
ScrollController
在Flutter中,Widget并不是最终渲染到屏幕上的元素(真正渲染的是RenderObject),因此通常这种监听事件以及相关的信息并不能直接从Widget中获取,而是必须通过对应的Widget的Controller来实现。
ListView、GridView的组件控制器是ScrollController,我们可以通过它来获取视图的滚动信息,并且可以调用里面的方法来更新视图的滚动位置。
另外,通常情况下,我们会根据滚动的位置来改变一些Widget的状态信息,所以ScrollController通?;岷蚐tatefulWidget一起来使用,并且会在其中控制它的初始化、监听、销毁等事件。
我们来做一个案例,当滚动到1000位置的时候,显示一个回到顶部的按钮:
jumpTo(double offset)、animateTo(double offset,...):这两个方法用于跳转到指定的位置,它们不同之处在于,后者在跳转时会执行一个动画,而前者不会。
ScrollController间接继承自Listenable,我们可以根据ScrollController来监听滚动事件。
classMyHomePageextendsStatefulWidget{
? @override
? State<StatefulWidget> createState() => MyHomePageState();
}
classMyHomePageStateextendsState{
? ScrollController _controller;
? bool _isShowTop = false;
? @override
? void initState() {
? ? // 初始化ScrollController
? ? _controller = ScrollController();
? ? // 监听滚动
? ? _controller.addListener(() {
? ? ? var tempSsShowTop = _controller.offset >= 1000;
? ? ? if (tempSsShowTop != _isShowTop) {
? ? ? ? setState(() {
? ? ? ? ? _isShowTop = tempSsShowTop;
? ? ? ? });
? ? ? }
? ? });
? ? super.initState();
? }
? @override
? Widget build(BuildContext context) {
? ? return Scaffold(
? ? ? appBar: AppBar(
? ? ? ? title: Text("ListView展示"),
? ? ? ),
? ? ? body: ListView.builder(
? ? ? ? itemCount: 100,
? ? ? ? itemExtent: 60,
? ? ? ? controller: _controller,
? ? ? ? itemBuilder: (BuildContext context, int index) {
? ? ? ? ? return ListTile(title: Text("item$index"));
? ? ? ? }
? ? ? ),
? ? ? floatingActionButton: !_isShowTop ? null : FloatingActionButton(
? ? ? ? child: Icon(Icons.arrow_upward),
? ? ? ? onPressed: () {
? ? ? ? ? _controller.animateTo(0, duration: Duration(milliseconds: 1000), curve: Curves.ease);
? ? ? ? },
? ? ? ),
? ? );
? }
}