前言
本文介紹 Flutter 中可滾動的 Widget滑蚯,主要有 ListView喷户、GridView和PageView。
一趴俘、ListView
ListView 是可以線性排列子Widget 的可滾動Widget蜗巧。ListView 可以和數(shù)據(jù)綁定用來實現(xiàn)瀑布流。
1. 使用方法
① 使用默認的構造函數(shù)蕾盯,給 children 屬性賦值
② 使用 ListView.builder幕屹,可用于和數(shù)據(jù)綁定實現(xiàn)大量或無限的列表
③ 使用 ListView.separated,具有分割項的 ListView.builder
④ 使用 ListView.custom级遭,需要使用 SliverChildDelegate
(1)使用默認的構造函數(shù)望拖,給 children 屬性賦值
- 使用場景:
適用于數(shù)據(jù)量少的情況 - 代碼示例:
import 'package:flutter/material.dart';
class ListViewDefaultWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new Scaffold(
appBar: new AppBar(
title: new Text('ListViewDefaultWidget'),
),
body: ListView(
children: <Widget>[
ListTile(
title: new Text('Title1'),
),
ListTile(
title: new Text('Title2'),
),
ListTile(
title: new Text('Title3'),
),
ListTile(
title: new Text('Title4'),
),
ListTile(
title: new Text('Title5'),
),
ListTile(
title: new Text('Title6'),
),
],
),
),
);
}
}
-
運行結果:
(2)使用 ListView.builder,可用于和數(shù)據(jù)綁定實現(xiàn)大量或無限的列表
- 使用場景:
適用于構建大量或無限的列表挫鸽,并且 ListView.builder 只會構建那些實際可見的子Widget说敏。
大部分屬性和 ListView 一樣,多了 itemCount 和 @required IndexedWidgetBuilder itemBuilder 屬性丢郊。
itemCount:代表子Widget 的數(shù)量盔沫,可以讓 ListView 預估最大滑動距離医咨,從而提升性能。如果不賦值架诞,為null拟淮,則子節(jié)點數(shù)由[itemBuilder]返回null的最小索引確定。
@required IndexedWidgetBuilder itemBuilder:itemBuilder 用于創(chuàng)建實際可見的子Widget谴忧,只有索引大于或等于零且小于 itemCount 才會調用 itemBuilder很泊。
- 代碼示例:
import 'package:flutter/material.dart';
void main() => runApp(ListViewBuilderWidget(
items: List<String>.generate(10000, (i) => "Item $I"),
));
class ListViewBuilderWidget extends StatelessWidget {
List<String> items;
ListViewBuilderWidget({Key key, @required this.items}) :super(key: key);
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new Scaffold(
appBar: new AppBar(
title: new Text('ListViewBuilderWidget'),
),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('${items[index]}'),
);
}),
),
);
}
}
(3)使用 ListView.separated,具有分割項的 ListView.builder
- 使用場景:
適用于需要分割線的列表沾谓。
相比 ListView.builder 多了一個 separatorBuilder委造。
- 代碼示例:
import 'package:flutter/material.dart';
class ListViewBuilderWidget extends StatelessWidget {
List<String> items;
ListViewBuilderWidget({Key key, @required this.items}) :super(key: key);
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new Scaffold(
appBar: new AppBar(
title: new Text('ListViewBuilderWidget'),
),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('${items[index]}'),
);
}),
),
);
}
}
-
運行結果:
(4)使用 ListView.custom,需要使用 SliverChildDelegate
- 使用場景:
SliverChildDelegate 有個默認實現(xiàn) SliverChildListDelegate均驶,我們可以用 SliverChildListDelegate 來實現(xiàn) ListView.custom昏兆。 - 代碼示例:
import 'package:flutter/material.dart';
class ListViewCustomWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new Scaffold(
appBar: new AppBar(
title: new Text('ListViewCustomWidget'),
),
body: ListView.custom(
childrenDelegate: new SliverChildListDelegate(<Widget>[
ListTile(
title: new Text('Title1'),
),
ListTile(
title: new Text('Title2'),
),
ListTile(
title: new Text('Title3'),
),
ListTile(
title: new Text('Title4'),
),
ListTile(
title: new Text('Title5'),
),
])),
),
);
}
}
2. ListView 的構造函數(shù)及參數(shù)說明
class ListView extends BoxScrollView {
ListView({
Key key,//可選;類型Key辣恋;Widget的標識
Axis scrollDirection = Axis.vertical,//可選亮垫;類型Axis;滑動的方向
bool reverse = false,//可選伟骨;類型bool饮潦;列表項的排列順序
ScrollController controller,//可選;類型ScrollController携狭;控制ListView的滾動位置
bool primary,//可選继蜡;類型bool;是否是父級關聯(lián)的主滾動視圖
ScrollPhysics physics,//可選逛腿;類型ScrollPhysics稀并;設置滾動效果
bool shrinkWrap = false,//可選;類型bool单默;是否根據(jù)列表項的總長度來設置ListView的長度
EdgeInsetsGeometry padding,//可選碘举;類型EdgeInsetsGeometry;ListView 的內邊距
this.itemExtent,//可選搁廓;類型double引颈;列表項的大小
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
int semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.down,
})
...
}
二、GridView
GridView 是一個可以構建二維網(wǎng)格列表的可滾動Widget境蜕。
1. 使用方法:
① 使用默認的構造函數(shù)蝙场,給 children 屬性賦值
② 使用 GridView.count
③ 使用 GridView.extent
④ 使用 GridView.builder,可用于和數(shù)據(jù)綁定實現(xiàn)大量或無限的列表
⑤ 使用 GridView.custom
(1)使用默認的構造函數(shù)粱年,給 children 屬性賦值
- 使用場景:
適用于使用少量 子Widget 的GridView - 代碼示例:
import 'package:flutter/material.dart';
class GridViewDefaultWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(title: new Text('Flutter 可滾動Widget -- GridView')),
body: GridView(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),//3列
children: <Widget>[
ListTile(
title: Text('Title1'),
),
ListTile(
title: Text('Title2'),
),
ListTile(
title: Text('Title3'),
),
ListTile(
title: Text('Title4'),
),
ListTile(
title: Text('Title5'),
),
ListTile(
title: Text('Title6'),
),
],
)),
);
}
}
-
運行結果:
(2)使用 GridView.count
將構造函數(shù)里的 gridDelegate 屬性售滤,拆分成了 crossAxisCount、mainAxisSpacing、crossAxisSpacing 和 childAspectRatio完箩。
- 代碼示例:
import 'package:flutter/material.dart';
class GridViewCountWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(title: new Text('Flutter 可滾動Widget -- GridView')),
body: GridView.count(
crossAxisCount: 3,
children: <Widget>[
ListTile(
title: Text('Title1'),
),
ListTile(
title: Text('Title2'),
),
ListTile(
title: Text('Title3'),
),
ListTile(
title: Text('Title4'),
),
ListTile(
title: Text('Title5'),
),
ListTile(
title: Text('Title6'),
),
],
)),
);
}
}
(3)使用 GridView.extent
布局算法不一樣
- 代碼示例:
import 'package:flutter/material.dart';
class GridViewExtentWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(title: new Text('Flutter 可滾動Widget -- GridView')),
body: GridView.extent(
maxCrossAxisExtent: 300,
children: <Widget>[
ListTile(
title: Text('Title1'),
),
ListTile(
title: Text('Title2'),
),
ListTile(
title: Text('Title3'),
),
ListTile(
title: Text('Title4'),
),
ListTile(
title: Text('Title5'),
),
ListTile(
title: Text('Title6'),
),
ListTile(
title: Text('Title7'),
),
],
)),
);
}
}
(4)使用 GridView.builder赐俗,可用于和數(shù)據(jù)綁定實現(xiàn)大量或無限的列表
- 使用場景:
用于構建大量或無限的列表,而且只會構建實際可見的子Widget嗜憔。 - 代碼示例:
import 'package:flutter/material.dart';
void main() => runApp(GridViewBuilderWidget(
items: List<String>.generate(10000, (i) => "Item $I"),
));
class GridViewBuilderWidget extends StatelessWidget {
final List<String> items;
GridViewBuilderWidget({Key key, @required this.items}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
home: Scaffold(
appBar: AppBar(title: new Text('Flutter 可滾動Widget -- GridView')),
body: GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('${items[index]}'),
);
},
),
),
);
}
}
(5)使用 GridView.custom
- 使用場景:
增加了 childrenDelegate 的屬性秃励,類型為 SliverChildDelegate,可以自定義子Widget吉捶。 - 代碼示例:
import 'package:flutter/material.dart';
void main() => runApp(GridViewCustomWidget(
items: List<String>.generate(10000, (i) => "Item $I"),
));
class GridViewCustomWidget extends StatelessWidget {
final List<String> items;
GridViewCustomWidget({Key key, @required this.items}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
home: Scaffold(
appBar: AppBar(title: new Text('Flutter 可滾動Widget -- GridView')),
body: GridView.custom(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
childrenDelegate: SliverChildListDelegate(<Widget>[
ListTile(
title: Text('Title1'),
),
ListTile(
title: Text('Title2'),
),
ListTile(
title: Text('Title3'),
),
ListTile(
title: Text('Title4'),
),
ListTile(
title: Text('Title5'),
),
ListTile(
title: Text('Title6'),
),
ListTile(
title: Text('Title7'),
),
ListTile(
title: Text('Title8'),
),
]),
),
),
);
}
}
2. GridView 構造函數(shù)和參數(shù)說明
class GridView extends BoxScrollView {
GridView({
Key key,//可選夺鲜;類型 Key;Widget的標識
Axis scrollDirection = Axis.vertical,//可選呐舔;類型 Axis币励;滑動的方向
bool reverse = false,//可選;類型 bool珊拼;列表項的排列順序
ScrollController controller,//可選食呻;類型 ScrollController;控制滾動位置
bool primary,//可選澎现;類型 bool仅胞;是否是與父級關聯(lián)的主滾動視圖
ScrollPhysics physics,//可選;類型 ScrollPhysics剑辫;設置滾動效果干旧,值必須為ScrollPhysics的子類,比如:AlwaysScrollableScrollPhysics():可以讓 GridView 里沒有足夠的內容也能滑動妹蔽,ScrollPhysics():GridView 在沒有足夠的內容的時候不能滑動
bool shrinkWrap = false,//可選椎眯;類型 bool;是否根據(jù)列表項的總長度來設置 GridView 的長度
EdgeInsetsGeometry padding,//可選胳岂;類型 EdgeInsetsGeometry编整;內邊距
@required this.gridDelegate,//必選;類型 SliverGridDelegate乳丰;控制子Widget布局的委托
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
int semanticChildCount,
})
...
}
三掌测、PageView
PageView 是可以一頁一頁滑動的可滾動Widget,類似 Android 中ViewPager产园。
1.使用方式:
① 使用默認的構造函數(shù)
② 使用 PageView.builder
③ 使用 PageView.custom
(1)使用默認的構造函數(shù)汞斧,給 children 屬性賦值
- 使用場景:
只適用于那些只有少量子Widget 的 PageView。 - 代碼示例:
import 'package:flutter/material.dart';
class PageViewDefaultWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(
title: new Text('PageViewDefaultWidget'),
),
body: PageView(
onPageChanged: (index) {
print('current page $index');
},
children: <Widget>[
ListTile(
title: new Text('Title0'),
),
ListTile(
title: new Text('Title1'),
),
ListTile(
title: new Text('Title2'),
),
ListTile(
title: new Text('Title3'),
),
ListTile(
title: new Text('Title4'),
),
],
),
),
);
}
}
-
運行結果:
(2) 使用 PageView.builder
- 使用場景:
用于構建大量和無限的列表淆两。而且只會構建那些實際可見的子Widget奕筐。 - 代碼示例:
多了 itemCount 和 itemBuilder 屬性
void main() => runApp(PageViewBuilderWidget(
items: List<String>.generate(10000, (i) => "Item $I"),
));
class PageViewBuilderWidget extends StatelessWidget {
final List<String> items;
PageViewBuilderWidget({Key key, @required this.items}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
home: Scaffold(
appBar: AppBar(title: new Text('Flutter 可滾動Widget -- PageView')),
body: PageView.builder(
onPageChanged: (index) {
print('current page $index ');
},
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('${items[index]}'),
);
},
),
),
);
}
}
(3)使用 PageView.custom
- 使用場景:
增加了childrenDelegate 的屬性踢涌,類型為 SliverChildDelegate,具有自定義子Widget 的能力插佛,不合適大量數(shù)據(jù)婶熬。 - 代碼示例:
import 'package:flutter/material.dart';
void main() => runApp(PageViewCustomWidget());
class PageViewCustomWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
home: Scaffold(
appBar: AppBar(title: new Text('Flutter 可滾動Widget -- PageView')),
body: PageView.custom(
onPageChanged: (index) {
print('current page $index ');
},
childrenDelegate: SliverChildListDelegate(<Widget>[
ListTile(title: Text('Title0')),
ListTile(title: Text('Title1')),
ListTile(title: Text('Title2')),
ListTile(title: Text('Title3')),
ListTile(title: Text('Title4')),
]),
)),
);
}
}
2. PageView 的構造函數(shù)和參數(shù)說明
class PageView extends StatefulWidget {
PageView({
Key key,//可選剑勾;類型 Key埃撵;Widget的標識
this.scrollDirection = Axis.horizontal,//可選;類型 Axis虽另;滑動方向
this.reverse = false,//可選暂刘;類型 bool;子Widget的排列順序
PageController controller,//可選捂刺;類型 PageController谣拣;控制滑動
this.physics,//可選;類型 ScrollPhysics族展;設置滾動效果
this.pageSnapping = true,//可選森缠;類型 bool;默認值false仪缸,用來禁止頁面捕捉贵涵,對自定義滾動行為有用
this.onPageChanged,//可選;類型 ValueChanged<int>恰画;監(jiān)聽頁面的切換
List<Widget> children = const <Widget>[],//可選宾茂;類型 List<Widget;PageView的列表項
this.dragStartBehavior = DragStartBehavior.down,//可選拴还;類型 DragStartBehavior跨晴;確定處理拖動開始行為的方式。如果設置為DragStartBehavior.start自沧,則在檢測到拖動手勢時將開始滾動拖動行為坟奥。如果設置為DragStartBehavior.down,它將在首次檢測到向下事件時開始
}) :
...
}
總結
本文主要介紹的可滾動的 Widget拇厢,ListView爱谁、GridView 和 PageView。除了這三個之外還有很多可以滾動的 Widget孝偎,如 SingleChildScrollView访敌、CustomScrollView 等等,若需要了解更多的 Widget 可以去查看官網(wǎng)的介紹https://flutter.dev/docs/development/ui/widgets/scrolling衣盾。