深入了解Flutter滚动组件
前言
本文适合有一定Flutter基础,但是对于Flutter滚动组件不够深入理解的同学。从应用场景入手,在合适的场景使用合适的组件。
ListView
单纯的使用ListView的话它会把列表数据全部渲染出来这样可能会有性能问题
ListView.builder
使用ListView.builder的话有虚拟列表的功能,它只会显示当前视口及视口之外的几个临近子组件,它是按照视口之外的高度作为参照渲染多出的组件的
ListView.separated
ListView.builder也有虚拟列表的功能但是比虚拟列表多出一个插入功能,比如可以在第一行和第二行之间插入组件
ListView.separated(
controller: _controller, // 控制滚动位置
// 安卓的效果:ClampingScrollPhysics
// IOS的效果:BouncingScrollPhysics
// 用户无法滚动:NeverScrollableScrollPhysics
// 自动对焦项目: FixedExtentScrollPhysics
physics: BouncingScrollPhysics(), // 控制滚动到边界的效果
separatorBuilder: (context, index) {
return Divider(); // 插入一个组件在两个项目中间
},
itemCount: 800,
itemBuilder: (context, index) {
return Text("index $index");
},
)
滚动条
- CupertinoScrollbar 按住可以拖动滚动条位置
- Scrollbar 默认的滚动条(无法拖动)
滚动效果
- 安卓波浪的效果:ClampingScrollPhysics
- IOS的拉伸效果:BouncingScrollPhysics
- 自动对齐某个项目: FixedExtentScrollPhysics
- 用户无法滚动:NeverScrollableScrollPhysics
// 自定义ScrollBehavior来清除操作系统上的默认滚动效果,有时候我们并不需要这些效果
class ClearEffectScrollBehavior extends ScrollBehavior {
@override
Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) {
return child;
}
}
刷新列表
RefreshIndicator(
onRefresh: () {
return Future.delayed(const Duration(seconds: 2)); // 等待两秒
},
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: 800,
itemBuilder: (context, index) {
return Text("index $index");
},
),
),
滑动移除某项
基于Dismissible组件来做的滑动移除效果
Dismissible(
key: UniqueKey(), // 必须传递Key
background: Container( // 背景其实不单只是颜色
child: Icon(Icons.ios_share_sharp),
),
onDismissed: (direction) { // 移除后的事件
print(direction);
},
onResize: () { // 移除后调整大小事件
print('resize');
},
direction: DismissDirection.vertical, // 可滑动的主轴方向
child: Container(
height: 80,
color: Colors.blue[100],
),
)
GridView
设置一行放置多少个元素:
- SliverGridDelegateWithFixedCrossAxisCount 按照指定数量
- SliverGridDelegateWithMaxCrossAxisExtent 按照能容纳比例放置
GridView.builder
可以达到虚拟列表的效果,缺点是需要写更多的代码,配合SliverGridDelegateWithFixedCrossAxisCount或SliverGridDelegateWithMaxCrossAxisExtent使用,达到一行展示多少个
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 8,
mainAxisSpacing: 5, // 主轴上元素之前的间距
crossAxisSpacing: 5, // 次轴上元素之前的间距
),
itemBuilder: (context, index) {
return Icon(Icons.abc);
},
),
GridView.extent和GridView.count
可以直接将一行展示多少个直接写在自己属性中,不需要额外的组件
GridView.extent(
maxCrossAxisExtent: 150, // 按照一行能够放下多少个来计算 一行的数量 = 屏幕宽度 / 150
children: [
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
],
);
GridView.count(
crossAxisCount: 5, // 一行必须放置5个
children: [
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
Icon(Icons.abc),
],
)
ListWheelScrollView
效果图
ListWheelScrollView(
itemExtent: 40, // 子级的大小
// offAxisFraction: -1.5, // 右边偏移量
magnification: 1.5, // 放大
useMagnifier: true, // 使用放大
diameterRatio: 2, // 圆的弧度
overAndUnderCenterOpacity: 0.5, // 中心项目透明度是0.5
physics: FixedExtentScrollPhysics(),
children: List.generate(
20,
(index) => Container(color: Colors.blue[300]),
),
)
PageView
多用于手势滑动切换整屏,这里有个头大的问题就是需要清除掉默认的滚动边界样式,通过自定义的 ClearEffectScrollBehavior 类实现清除
安卓上的滚动边界样式(小波浪)
PageView(
controller: PageController(),
pageSnapping: false, // 取消自动对齐
scrollBehavior: ClearEffectScrollBehavior(), // 清除默认的滚动边界样式,你也可以直接用于根MetairieApp组件中
onPageChanged: (val) { // 滑动到某个页面组件,在没有松手的情况下也会触发这个事件
print(val);
},
children: [
Container(
color: Colors.amber,
),
Container(
color: Colors.blue[200],
)
],
)
class ClearEffectScrollBehavior extends ScrollBehavior {
@override
Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) {
return child;
}
}
ReorderableListView
实现按住拖动排序的功能
ReorderableListView(
onReorder: (int oldIndex, int newIndex) {
print(oldIndex);
print(newIndex);
},
children: List.generate(
20,
(index) => Container(
key: UniqueKey(),
color: Colors.orange,
child: Text('index $index'),
),
),
)
SingleChildScrollerView
我们需要滚动的时候再出现滚动的行为,不需要滚动的时候不会出现任何可滚动的征兆。
它和其他滚动组件的区别就在于,内容如果没有超过页面宽或高的时候不会出现任何能够滚动的特征。(例如:安卓中的上滚动到容器边界会出现波浪效果,或者IOS上的拉伸效果)
我们应该在将合适的组件应用于合适的场景中,不能盲目使用ListView哦
IOS上的的拉伸效果
ReorderableListView(
onReorder: (int oldIndex, int newIndex) { // 拖动后的排序函数,这个排序需要自己手动来排序
print(oldIndex);
print(newIndex);
},
children: List.generate(
20,
(index) => Container(
key: UniqueKey(),
color: Colors.orange,
child: Text('index $index'),
),
),
)
如何加入比特鹰
目前我们在招聘的岗位有:投研分析师,Python 后端研发工程师,前端研发工程师,AI研发工程师。
可以将简历投递到邮箱 join@bitying.cn
转载自:https://juejin.cn/post/7250144333056245818