Flutter学习笔记之-滚动Widget的基础使用
- ListView
通过官方文档可知ListView的创建方式有很多,可以根据实际情况选择使用方式
1、默认构造函数
2、ListView.builder方法,可以显示大量数据的ListView
3、ListView.separated可以添加分割线
4、ListView.custom自定义的方式
1、默认构造函数的方式
class DemoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
itemExtent: 100, // 行高
padding: const EdgeInsets.all(8),
children: <Widget>[
Container(
height: 50,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 50,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
],
);
}
}
ListTile的默认样式:
有一个图标或图片(Icon),有一个标题(Title),有一个子标题(Subtitle),还有尾部一个图标(Icon)
class DemoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
itemExtent: 100, // 行高
padding: const EdgeInsets.all(8),
children: <Widget>[
ListTile(
leading: Icon(Icons.people, size: 36,),
title: Text("联系人"),
subtitle: Text("联系人信息"),
trailing: Icon(Icons.arrow_forward_ios),
),
ListTile(
leading: Icon(Icons.email, size: 36,),
title: Text("邮箱"),
subtitle: Text("邮箱地址信息"),
trailing: Icon(Icons.arrow_forward_ios),
),
],
);
}
}
横向滚动的布局方式
class DemoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
height: 100,
child: ListView(
// 滚动方向,横向滚动
scrollDirection: Axis.horizontal,
itemExtent: 300, // 行高
padding: const EdgeInsets.all(8),
children: <Widget>[
Container(
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
],
),
);
}
}
2、ListView.builder方式创建ListView
class DemoFulWidget extends StatefulWidget {
@override
_DemoFulWidgetState createState() => _DemoFulWidgetState();
}
class _DemoFulWidgetState extends State<DemoFulWidget> {
final List<String> entries = <String>['A', 'B', 'C'];
final List<int> colorCodes = <int>[600, 500, 100];
@override
Widget build(BuildContext context) {
return ListView.builder(
padding: EdgeInsets.all(10),
itemExtent: 50,
itemCount: entries.length,
itemBuilder: (BuildContext context, int index) {
return Container(
child: Text("Hello world - ${entries[index]}"),
color: Colors.amber[colorCodes[index]],
);
});
}
}
3、 ListView.separated可以添加分割线
class DemoFulWidget extends StatefulWidget {
@override
_DemoFulWidgetState createState() => _DemoFulWidgetState();
}
class _DemoFulWidgetState extends State<DemoFulWidget> {
final List<String> entries = <String>['A', 'B', 'C'];
final List<int> colorCodes = <int>[600, 500, 100];
@override
Widget build(BuildContext context) {
return ListView.separated(
padding: EdgeInsets.all(10),
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
child: Text("Hello world - ${entries[index]}"),
color: Colors.amber[colorCodes[index]],
);
}, separatorBuilder: (BuildContext context, int index) {
return Divider(
height: 10,
indent: 10, // 距离左边的位置
color: Colors.red,);
}, itemCount: entries.length);
}
}
- GridView
GridView类似于iOS上的UICollectionView
1、GridView.count实现方式
class DemoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GridView.count(
crossAxisCount: 2,
primary: false,
padding: const EdgeInsets.all(20),
// 次轴方向上的间隔
crossAxisSpacing: 10,
// 主轴方向上的间隔
mainAxisSpacing: 10,
children: <Widget>[
Container(
padding: const EdgeInsets.all(8),
child: const Text("He'd have you all unravel at the"),
color: Colors.teal[100],
),
Container(
padding: const EdgeInsets.all(8),
child: const Text('Heed not the rabble'),
color: Colors.teal[200],
),
Container(
padding: const EdgeInsets.all(8),
child: const Text('Sound of screams but the'),
color: Colors.teal[300],
),
Container(
padding: const EdgeInsets.all(8),
child: const Text('Who scream'),
color: Colors.teal[400],
),
Container(
padding: const EdgeInsets.all(8),
child: const Text("He'd have you all unravel at the"),
color: Colors.teal[100],
),
Container(
padding: const EdgeInsets.all(8),
child: const Text('Heed not the rabble'),
color: Colors.teal[200],
),
Container(
padding: const EdgeInsets.all(8),
child: const Text('Sound of screams but the'),
color: Colors.teal[300],
),
Container(
padding: const EdgeInsets.all(8),
child: const Text('Who scream'),
color: Colors.teal[400],
)
],
);
}
}
2、GridView使用gridDelegate方式创建
方式一采用默认构造方式
class _MyHomePageState extends State<MyHomePage> {
List<Widget> getChildrenWidgets() {
return List.generate(20, (index) {
return Container(child: Text("grid item $index"), color: Colors.red, alignment: Alignment.center,);
}
);
}
@override
Widget build(BuildContext context) {
return GridView(
children: getChildrenWidgets(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, mainAxisSpacing: 10, crossAxisSpacing: 10),
);
}
}
方式二利用GridView.builder的方式创建
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, mainAxisSpacing: 10, crossAxisSpacing: 10),
itemBuilder: (BuildContext context, int index) {
return Container(child: Text("grid item $index"), color: Colors.red, alignment: Alignment.center,);
});
}
3、GridView实现滚动监听
class _MyHomePageState extends State<MyHomePage> {
ScrollController _scrollController;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
_scrollController.addListener(() {
// 打印位置监听数据
print("lister = ${_scrollController.offset}");
if (_scrollController.offset >= 1000) {
// 滚动到起始位置
_scrollController.animateTo(0, duration: Duration(seconds: 2), curve: Curves.easeInCirc);
}
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_scrollController.dispose();
}
@override
Widget build(BuildContext context) {
return GridView.builder(
controller: _scrollController,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, mainAxisSpacing: 10, crossAxisSpacing: 10),
itemBuilder: (BuildContext context, int index) {
return Container(
child: Text("grid item $index"),
color: Colors.red,
alignment: Alignment.center,);
});
}
}
4、GridView监听滚动开始、结束、滚动中的状态
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return NotificationListener(
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, mainAxisSpacing: 10, crossAxisSpacing: 10),
itemBuilder: (BuildContext context, int index) {
return Container(
child: Text("grid item $index"),
color: Colors.red,
alignment: Alignment.center,);
}),
onNotification: (ScrollNotification notification) {
if (notification is ScrollStartNotification) {
print("开始滚动");
} else if (notification is ScrollUpdateNotification) {
print("滚动中..");
} else if (notification is ScrollEndNotification) {
print("滚动结束");
}
return false;
},
);
}
}
- CustomScrollView
1、利用CustomScrollView实现GridView的效果,分别用SliverSafeArea增加安全区域显示,SliverPadding实现SliverGrid间距。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverSafeArea( // 安全区域
sliver: SliverPadding( // 添加间距
padding: EdgeInsets.all(10),
sliver: SliverGrid(delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(child: Text("grid item $index"),
color: Colors.red,
alignment: Alignment.center);
}, childCount: 20
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, mainAxisSpacing: 10, crossAxisSpacing: 10)),
),
)
],
);
}
}
2、利用CustomScrollView实现GridView+ListView的效果
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverAppBar(
expandedHeight: 250.0,
flexibleSpace: FlexibleSpaceBar(
title: Text('Coderwhy Demo'),
background: Image(
image: NetworkImage(
"https://tva1.sinaimg.cn/large/006y8mN6gy1g72j6nk1d4j30u00k0n0j.jpg",
),
fit: BoxFit.cover,
),
),
),
SliverGrid(delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(child: Text("grid item $index"),
color: Colors.red,
alignment: Alignment.center);
}, childCount: 9
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, mainAxisSpacing: 10, crossAxisSpacing: 10)
),
SliverFixedExtentList(
itemExtent: 50.0,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: new Text('list item $index'),
);
},
childCount: 20
),
),
],
);
}
}