Flutter学习之滚动监听
Posted 隔壁小王66
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter学习之滚动监听相关的知识,希望对你有一定的参考价值。
ScrollController
构造方法
ScrollController(
double initialScrollOffset = 0.0, //初始化滑动距离
this.keepScrollOffset = true,//是否保存滑动距离
this.debugLabel,
) : assert(initialScrollOffset != null),
assert(keepScrollOffset != null),
_initialScrollOffset = initialScrollOffset;
属性 | 含义 |
---|---|
initialScrollOffset | 初始化滑动距离 |
keepScrollOffset | 是否保存滑动距离,默认true |
例如:
ScrollController _scrollController = new ScrollController(initialScrollOffset: 1000);
设置初始化滑动距离为1000像素,打开页面时就已经滑动1000距离,不会触发监听
常用方法
方法 | 含义 |
---|---|
addListener | 滑动监听方法,在initState中监听 |
_scrollController.position.pixels | 滑动距离 |
_scrollController.offset | 滑动距离 |
_scrollController.position.maxScrollExtent | 最大可滑动距离,滑动组件内容长度 |
_scrollController.position.minScrollExtent | 最小可滑动距离,0 |
_scrollController.position.viewportDimension | 滑动视图所占长度 |
_scrollController.dispose() | 销毁监听,在dispose方法中调用 |
_scrollController.jumpTo | 控制滑动组件的滑动距离,无动画 |
_scrollController.animateTo(10); | 控制滑动组件的滑动距离,有动画 |
_scrollController.position.jumpTo | 同上 |
_scrollController.position.animateTo | 同上 |
ScrollPosition
ScrollController中包含一个ScrollPosition,里面包含的信息更加丰富,如果一个ScrollController监听多个滑动widget,可以用ScrollPosition加以区分
_scrollController.positions获取监听对象集合,然后取出各个监听的ScrollPosition,来获取滑动的一些信息
例如:_scrollController.positions.elementAt(0).pixels;
实现ScrollController滑动监听
class Scontroller extends State<Sc>
ScrollController _scrollController = new ScrollController();
bool isShow = false;
@override
void initState()
// TODO: implement initState
super.initState();
_scrollController.addListener(()
int offset = _scrollController.position.pixels.toInt();
print("滑动距离$offset");
// 如果滑动到底部
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent)
setState(()
isShow = true;
);
else
setState(()
isShow = false;
);
);
@override
void dispose()
// TODO: implement dispose
_scrollController.dispose();
super.dispose();
@override
Widget build(BuildContext context)
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("滑动控制"),
),
body: Container(
padding: EdgeInsets.all(20),
child: Scrollbar(
child: ListView.separated(
physics: BouncingScrollPhysics(),
controller: _scrollController,
itemBuilder: (BuildContext buildContext, int index)
return ListTile(
title: Text("标题"),
subtitle: Text("副标题$index"),
onTap: ()
print("$index");
,
);
,
separatorBuilder: (BuildContext buildContext, int index)
return Divider(
color: Colors.grey,
);
,
itemCount: 50)),
),
floatingActionButton: !isShow
? null
: FloatingActionButton(
onPressed: ()
_scrollController.position.jumpTo(10);
,
child: Icon(Icons.arrow_upward),
),
);
效果如下:
NotificationListener
NotificationListener是一个用来监听子widget滑动的widget
Flutter Widget树中子Widget可以通过发送通知(Notification)与父(包括祖先)Widget通信。父级组件可以通过NotificationListener组件来监听自己关注的通知
可滚动组件在滚动时会发送ScrollNotification类型的通知,ScrollBar正是通过监听滚动通知来实现的。通过NotificationListener监听滚动事件和通过ScrollController有两个主要的不同:
1、通过NotificationListener可以在从可滚动组件到widget树根之间任意位置都能监听。而ScrollController只能和具体的可滚动组件关联后才可以。
收到滚动事件后获得的信息不同;2、NotificationListener在收到滚动事件时,通知中会携带当前滚动位置和ViewPort的一些信息,而ScrollController只能获取当前滚动位置。
实现例子:
class Scontroller1 extends State<Sc>
ScrollController _scrollController = new ScrollController(initialScrollOffset: 1000);
bool isShow = false;
String _progress = "0%";
@override
void initState()
// TODO: implement initState
super.initState();
_scrollController.addListener(()
int offset = _scrollController.position.viewportDimension.toInt();
print("滑动距离$offset");
// 如果滑动到底部
if (_scrollController.offset ==
_scrollController.position.maxScrollExtent)
setState(()
isShow = true;
);
else
setState(()
isShow = false;
);
);
@override
void dispose()
// TODO: implement dispose
_scrollController.dispose();
super.dispose();
@override
Widget build(BuildContext context)
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("滑动控制"),
),
body: Container(
padding: EdgeInsets.all(20),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Scrollbar(
child: NotificationListener(
onNotification: (ScrollNotification notification)
//滑动进度/最大可滑动进度
double progress = notification.metrics.pixels /
notification.metrics.maxScrollExtent;
setState(()
_progress = "$((progress * 100).toInt())%";
);
,
child: ListView.separated(
physics: BouncingScrollPhysics(),
controller: _scrollController,
itemBuilder: (BuildContext buildContext, int index)
return ListTile(
title: Text("标题"),
subtitle: Text("副标题$index"),
onTap: ()
print("$index");
,
);
,
separatorBuilder: (BuildContext buildContext, int index)
return Divider(
color: Colors.grey,
);
,
itemCount: 50)),
),
CircleAvatar(
//显示进度百分比
radius: 30.0,
child: Text(_progress),
backgroundColor: Colors.black54,
),
],
),
),
floatingActionButton: !isShow
? null
: FloatingActionButton(
onPressed: ()
_scrollController.jumpTo(10);
,
child: Icon(Icons.arrow_upward),
),
);
效果
使用方法
NotificationListener(
onNotification: (ScrollNotificati notification)
//do something
,
child:Widget
)
看一下ScrollNotification包含了什么
ScrollNotification(
@required this.metrics,
@required this.context,
);
metrics对象包含了什么
ScrollMetrics copyWith(
double minScrollExtent,
double maxScrollExtent,
double pixels,
double viewportDimension,
AxisDirection axisDirection,
)
ScrollNotification拿到的是一个包含滑动信息的对象
以上是关于Flutter学习之滚动监听的主要内容,如果未能解决你的问题,请参考以下文章