flutter ListView
本文最后更新于:2022年4月22日 上午
页面滚动 ListView
ListView
flutter中需要通过 ListView才能够让页面进行滚动
ListView的基本使用
itemExtent指定子元素的 宽或者高(根据展示的方向),显示指定更有利于优化性能,
return ListView(
// 指定子元素的 宽或者高(根据展示的方向),显示指定更有利于优化性能,
itemExtent: 100,
children: [
Text('1'),
Text('2'),
Text('3'),
Text('4'),
],
);
list.generate
可以快速生成多个元素
return ListView(
children: List.generate(100, (index) => Text('内容$index')),
);ListView.separated 分割线
ListView.separated有一个separatorBuilder属性来设置分割线
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
return Text('内容$index');
},
separatorBuilder: (BuildContext context, int index) {
// 分割线
return Divider(
color: Colors.green,
thickness: 2,
indent: 10,
endIndent: 10,
);
},
itemCount: 100
);Divider
分割线 widget
ListView.builder
这个性能会相对更好一些,它会在item即将展示的时候再进行构建,且可通过配置来修改预渲染的范围
return ListView.builder(
itemCount: 50,
itemExtent: 50,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('联系人$index'),
subtitle: Text('1777828617$index'),
leading: Icon(Icons.person),
trailing: Icon(Icons.call_end),
);
}
);ListTile
一个由前缀,后缀,title,subTitle的widget,比较适合用来展示联系人
gridView.builder 网格布局
可以给 gridDelegate来设置 SliverGridDelegateWithMaxCrossAxisExtent或者SliverGridDelegateWithFixedCrossAxisCount来修改交叉轴是根据 个数 还是 最大宽 来布局侧轴的排列
可以通过添加 controller来完成返回顶部的操作,返回顶部可以让值设置为负值 -20,这样会有一个反弹的效果
也可以实现向下翻页的效果 _controller.jumpTo(_controller.offset + (屏幕高度 - appbar高度) )
return GridView.builder(
controller: _controller,
itemExtent: 100, // 每个item最大主轴方向 高度/宽度 约束,设置这个可以让滚动条正确计算
itemCount: 100,
// 设置交叉轴的 item 个数
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
// 通过 主轴 设置占据的最大值来设置 item
gridDelegate:
SliverGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 100, mainAxisSpacing: 5, crossAxisSpacing: 5),
itemBuilder: (BuildContext context, index) {
return Container(
width: 100,
height: 100,
color: Color.fromRGBO(
Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), Random().nextInt(10) / 10),
);
},
);physics属性的作用
flutter会根据操作系统来模拟不同的效果,如果需要手动设置效果反弹效果可以手动设置
BouncingScrollPhysicsios 效果ClampingScrollPhysicsandroid 效果[NeverScrollableScrollPhysics](https://api.flutter-io.cn/flutter/widgets/NeverScrollableScrollPhysics/NeverScrollableScrollPhysics.html)不可滚动,可以通过controller来操作滚动[AlwaysScrollableScrollPhysics](https://api.flutter-io.cn/flutter/widgets/AlwaysScrollableScrollPhysics/AlwaysScrollableScrollPhysics.html)永远可以滚动FixedExtentScrollPhysics精准的停留在某个元素上
ListView.builder(
physics: BouncingScrollPhysics()
);文档 https://api.flutter-io.cn/flutter/widgets/ScrollPhysics-class.html
Random
dart 中用来生成随机数的函数
ListWheelScrollView 3d效果滚动
类似于ios 上 时间选择器的效果
ListWheelScrollView({
Key? key,
this.controller,
this.physics, // 使用 FixedExtentScrollPhysics() 可以精准的停留在某个item上
this.diameterRatio = RenderListWheelViewport.defaultDiameterRatio, // 直径比例,上下的高度
this.perspective = RenderListWheelViewport.defaultPerspective,
this.offAxisFraction = 0.0, // 与轴心的偏移
this.useMagnifier = false, // 中间元素是否开启放大镜
this.magnification = 1.0, // 中间元素的缩放大小
this.overAndUnderCenterOpacity = 1.0, // 上下的非选中元素的透明度
required this.itemExtent, // 子元素的高度
this.squeeze = 1.0,
this.onSelectedItemChanged, // 选中后的回调
this.renderChildrenOutsideViewport = false,
this.clipBehavior = Clip.hardEdge,
this.restorationId,
this.scrollBehavior,
required List<Widget> children,
})PageView 轮播图滚动效果
PageView({
Key? key,
this.scrollDirection = Axis.horizontal, // 水平方向滚动
this.reverse = false,
PageController? controller,
this.physics,
this.pageSnapping = true, // 是否可使页面停留在一半效果
this.onPageChanged, // 选择后回调
List<Widget> children = const <Widget>[],
this.dragStartBehavior = DragStartBehavior.start,
this.allowImplicitScrolling = false,
this.restorationId,
this.clipBehavior = Clip.hardEdge,
this.scrollBehavior,
this.padEnds = true,
})ReorderableListView
ReorderableListView拖拽列表
SingleChildScrollView
和 ListView的区别是,在高度不足以滚动的时候,用户是感受不到滚动的回弹效果的,ListView如果在元素少的时候依旧可以感受到滚动的回弹效果
SingleChildScrollView 较少用,一般用于 默认情况下不需要滚动,但是某些情况有可能需要滚动的时候
SingleChildScrollView(
child: Column()
)Column嵌套 ListView
通过 Expanded将 ListView进行包裹
因为 Column会讲自己向下级传递的约束伪装成 无限高的,如果直接嵌套 ListView,那么ListView也会将自己的高度设置为无限高,这时候高度就出现问题了,而通过 Expanded就可以避免这问题
例如Column把其它的非弹性元素布局完后发现只剩下600高度,那么就会把600高度的约束平均分给 Expanded
Column(
children: [
FlutterLogo(size: 50),
Expanded(
child: ListView(children: [])
)
]
)CustomScrollView 同时使用 ListView 和 GridView
如果项目中出现 同时使用 ListView 和 GridView的需求的话,就需要通过自定义 ScrollView的方式来实现,因为ListView 和 GridView本质也是这个,只是往里面插入了一个元素return <Widget>[ sliver ];
SliverList: ListView的本质
SliverGrid: GridView 的本质
通过直接使用 SliverList和SliverGrid来构建自定义ListView和GridView
通过给 delegate设置为SliverChildBuilderDelegate来构建子元素
// 同时使用 ListView 和 GridView, 自定义 ScrollView
return CustomScrollView(
slivers: [
SliverAppBar(
title: Text('标题'),
),
SliverList(
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
return ListTile(
title: Text('联系人$index'),
subtitle: Text('1777828617$index'),
leading: Icon(Icons.person),
trailing: Icon(Icons.call_end),
);
}, childCount: 20)),
SliverGrid(
delegate: SliverChildBuilderDelegate((BuildContext context, index) {
return Container(
width: 100,
height: 100,
color: Color.fromRGBO(
Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), Random().nextInt(10) / 10),
);
}, childCount: 20),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3))
],
);如果要在slivers中放普通元素,需要使用 SliverToBoxAdapter进行一个简单的转接
SliverAppBar
安全区域内的 appBar
SliverSafeArea 安全区域
在通过包裹 SliverSafeArea来让内容在安全区域内展示,放只在刘海和屏幕底部的操作栏遮挡
return CustomScrollView(
controller: _scrollController,
slivers: [
SliverSafeArea(
sliver: SliverPadding(
padding: EdgeInsets.all(5),
sliver: SliverGrid(
delegate: SliverChildBuilderDelegate((BuildContext context, index) {
return Container(
width: 100,
height: 100,
color: Color.fromRGBO(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1),
);
}, childCount: 50),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, mainAxisSpacing: 5, crossAxisSpacing: 5),
),
))
],
);SliverPadding
可以在安全区域设置外padding
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。