滚动组件笔记
滚动列表与动态加载
ListView.builder(
physics: const BouncingScrollPhysics(), // 末端继续滑动的效果,回弹
controller: _scrollController, // 控制器
padding: const EdgeInsets.all(50), // ListView的Padding
cacheExtent: 200, // 缓冲区像素,一般不用设置
itemExtent: 100, // 每个item的高度,用于item高度不同使用Scrollbar跳转时的性能优化
itemBuilder: (context, index) {
return Container(
width: double.infinity,
height: 100,
color: Colors.blue[(index % 5) * 100],
alignment: Alignment.center,
child: Text('$index'),
);
},
itemCount: 900, // 列表item个数,不填就是无限个
),
加载下一页
定义一个controller
final _scrollController = ScrollController();
利用offset属性和jumpto方法滑动
onPressed: () {
final now = _scrollController.offset; // 获取当前列表偏移量
_scrollController.animateTo(now + 700, // 每次向下滑动700像素单位
duration: const Duration(milliseconds: 300), curve: Curves.ease);
},
回到顶部
onTap: () {
_scrollController.animateTo(
-20.0, // 如果是负数,会回弹到0.0,更加自然
duration: const Duration(milliseconds: 300),
curve: Curves.ease,
);
},
显示滚动条
// 在ScrollView外面套一个Scrollbar即可,还可以设置滚动条的位置和风格,ios默认是CupertinoScrollbar,android是RawScrollBar
Scrollbar(
controller: _scrollController, // 这一层和滚动层都需要设置相同的controller,否则会报错
child: ListView.builder(
physics: const BouncingScrollPhysics(),
controller: _scrollController,
padding: const EdgeInsets.all(50),
cacheExtent: 200,
itemExtent: 100,
itemBuilder: (context, index) {
return Container(
width: double.infinity,
height: 100,
color: Colors.blue[(index % 5) * 100],
alignment: Alignment.center,
child: Text('$index'),
);
},
itemCount: 900,
),
),
下拉刷新
RefreshIndicator(
strokeWidth: 3.0,
color: Colors.white,
backgroundColor: Colors.amber,
onRefresh: () {
return Future.delayed(const Duration(seconds: 2)); // 模拟异步操作
},
child: ListView.builder(...
通知事件
NotificationListener(
onNotification: (notification) {
print(notification);
return false; // 返回false则事件继续冒泡,true则截停事件冒泡,结果是父级需要用到通知的组件会失效
},
child: ListView.builder(...
支持滑动删除的Dismissible
ListView.builder(
physics: const BouncingScrollPhysics(),
controller: _scrollController,
itemBuilder: (context, index) {
return Dismissible( // 用Dismissible嵌套
key: UniqueKey(), // key必传
background: Container( // 滑动底部背景(主,从左到右,startToEnd)
color: Colors.green,
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(left: 16),
child: const Icon(
Icons.phone,
color: Colors.white,
),
),
secondaryBackground: Container( // 和如上属性相反
color: Colors.amber,
alignment: Alignment.centerRight,
padding: const EdgeInsets.only(right: 16),
child: const Icon(
Icons.message,
color: Colors.white,
),
),
onDismissed: (direction) { // 滑动消失的方向,左面是start右面是end
print(direction);
},
confirmDismiss: (direction) async { // 是否真的要删除,是异步函数,返回ture删除,false不删除
await Future.delayed(const Duration(seconds: 1));
return true;
},
onResize: () { // 删除后剩余item重新布局的过程
print('on resizing');
},
resizeDuration: const Duration(seconds: 2), // 重新布局过渡时间
movementDuration: const Duration(seconds: 5), // 删除滑动或恢复的时间
dismissThresholds: const { // 设置滑动方向对应的阈值,默认是0.4
DismissDirection.startToEnd: 0.1,
DismissDirection.endToStart: 0.8
},
child: Container(
width: double.infinity,
height: 100,
color: Colors.blue[(index % 5) * 100],
alignment: Alignment.center,
child: Text('$index'),
),
);
},
itemCount: 900,
),
ListWheelScrollView(选择器效果)
ListWheelScrollView(
children: List.generate(
20,
(index) => Container(
// color: Colors.amber,
child: Text('hello$index',style: TextStyle(fontSize: 72),),
alignment: Alignment.center,
),
),
itemExtent: 100, // 单个元素高度
offAxisFraction: -1.2, // 扭曲偏移
overAndUnderCenterOpacity: .5, // 未选中的透明度
useMagnifier: true, // 使用放大镜
diameterRatio: 1.5, // 调整绕3D圆心转动时的转动半径(可以这么理解)
physics: FixedExtentScrollPhysics(), // 始终固定到某一项
onSelectedItemChanged: (value) { // 选择事件
print('select $value');
},
),
无法设置横向滚动,必须使用的话要在外层套一个RotateView
PageView
PageView(
pageSnapping: true, // 始终吸附固定,显示某一个整页
scrollDirection: Axis.horizontal, // 方向
onPageChanged: (index) {
print('$index');
},
children: List.generate(
7,
(index) => Container(
color: Colors.amber[(index + 1) * 100],
alignment: Alignment.center,
child: Text(
'page$index',
style: TextStyle(fontSize: 72),
),
),
),
),
ReorderableListView(拖拽)
ReorderableListView(
children: List.generate(
20,
(index) => Text(
'index is $index',
key: UniqueKey(), // 必须传一个key
textAlign: TextAlign.center,
),
),
onReorder: (oldIndex, newIndex) { // 拖动释放事件
print('move from $oldIndex to $newIndex');
},
),