這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰緩存
相關文章:Flutter listview下拉刷新 上拉加載更多 (juejin.cn)markdown
#前言: 今天就來介紹下Flutter中的列表組件ListView和網格組件GirdView,嗯,果真是Google家的親兒子,連名字都和Android裏的如出一轍。 好的吧,咱們仍是來看下這兩個Widget的用法吧app
#ListView ListView就是咱們常見的列表組件,在平時的應用開發中十分的常見,不管你作的是什麼類型的應用都會多多少少會用到ListView,因此要好好看下這篇文章哦less
仍是先來看下listView的構造方法:ide
ListView({
Key key,
Axis scrollDirection: Axis.vertical,//滾動方向
bool reverse: false,//是否反向顯示數據
ScrollController controller,
bool primary,
ScrollPhysics physics,//物理滾動
bool shrinkWrap: false,
EdgeInsetsGeometry padding,
this.itemExtent,//item有效範圍
bool addAutomaticKeepAlives: true,//自動保存視圖緩存
bool addRepaintBoundaries: true,//添加劇繪邊界
List<Widget> children: const <Widget>[],
})
複製代碼
那麼,咱們仍是來看下具體的用法oop
咱們仍是按照慣例在Scaffold裏放一個ListViewpost
import 'package:flutter/material.dart';
class Routes extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('目錄')),
body: new ListView(
children: <Widget>[
ListTile(
title: Text('標題1'),
leading: Icon(Icons.build),
trailing: Text('尾巴'),
onTap: () {
showDialog(
context: context,
child: new SimpleDialog(
contentPadding: const EdgeInsets.all(10.0),
title: new Text("我是標題"),
children: <Widget>[new Text("我是內容區域")],
));
},
),
ListTile(
title: Text('標題2'),
leading: Icon(Icons.print),
trailing: Text('尾巴'),
),
ListTile(
title: Text('標題3'),
leading: Icon(Icons.library_music),
trailing: Text('尾巴'),
),
ListTile(
title: Text('標題4'),
leading: Icon(Icons.accessibility_new),
trailing: Text('尾巴'),
),
],
),
);
}
}
複製代碼
children參數咱們傳入了4個ListTile,先介紹下: ListTile是一個固定高度的行,一般包含一些文本,以及一個行前或行尾圖標。測試
const ListTile({
Key key,
this.leading,
this.title,
this.subtitle,
this.trailing,
this.isThreeLine = false,
this.dense,
this.contentPadding,
this.enabled = true,
this.onTap,
this.onLongPress,
this.selected = false,
}) : assert(isThreeLine != null),
assert(enabled != null),
assert(selected != null),
assert(!isThreeLine || subtitle != null),
super(key: key);
複製代碼
而後咱們來看下效果 ![這裏寫圖片描述] (img-blog.csdn.net/20180905161…)ui
固然,因爲數據量過少它如今是不能滑動的。你們能夠在下面多加幾個Widget試試效果。this
在Flutter中有三種構建ListView的方式,剛纔介紹的是最簡單的一種,可是卻不是最經常使用的,由於它僅僅適用於已知數量或者較少數量的Item的狀況。若是有未知數量或者無限個Item的狀況,再使用上述的方法將再也不適用。
那麼,咱們能夠嘗試下ListView.builder()
和ListView.custom()
。
ListView.builder()和ListView.custom()的用法基本相同,只不過custom能夠根據本身的須要控制Item顯示方式,如Item顯示大小。
咱們今天來看下ListView.builder()
ListView.builder({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
this.itemExtent,
@required IndexedWidgetBuilder itemBuilder, //item構建者
int itemCount, //item數量
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double cacheExtent,
})
複製代碼
相比於new ListView()只不過多出了兩個參數而已,一個是itemCount指定item的數量,一個是itemBuilder,用來構建Item。
看下用法
import 'package:flutter/material.dart';
class ListItem {
final String title;
final IconData iconData;
ListItem(this.title, this.iconData);
}
class ListItemWidget extends StatelessWidget {
final ListItem listItem;
ListItemWidget(this.listItem);
@override
Widget build(BuildContext context) {
return new ListTile(
leading: new Icon(listItem.iconData),
title: new Text(listItem.title),
);
}
}
class Routes extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return RouteState();
}
}
class RouteState extends State<Routes> {
final List<ListItem> listData = [];
@override
void initState() {
super.initState();
for (int i = 0; i < 20; i++) {
listData.add(ListItem("我是測試標題$i", Icons.cake));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('列表'),
),
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListItemWidget(listData[index]);
},
itemCount: listData.length,
),
);
}
}
複製代碼
咱們首先新建了一個ListItem對象,icon和title兩個屬性 咱們新建了一個一個Widget,須要傳入ListItem對象,藉助於ListItem對象的屬性初始化ListTitle。 而後在initState方法中初始化listData,建立了20個ListItem對象。
在itemBuilder中返回指定的的Listitem到ListItemWidget對象中,返回指定的ListItemWidget對象。
經過這種方法,咱們不須要關注Item的數量,由於咱們每一個Item都是自動構建的,而且大大減小重複代碼的數量。 下面來看下GridView
#GridView GirView的用法和ListView相似,只不過因爲GridView能夠在一列或者一行顯示多個Item,因此在構造方法中就多了個參數
GridView({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
@required this.gridDelegate, //沒錯,它就是控制GridView的
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
})
複製代碼
看下gridDelegate參數
能夠傳入SliverGridDelegateWithFixedCrossAxisCount
對象和SliverGridDelegateWithMaxCrossAxisExtent
對象。 其中SliverGridDelegateWithFixedCrossAxisCount
能夠直接指定每行(列)顯示多少個Item,SliverGridDelegateWithMaxCrossAxisExtent
會根據GridView的寬度和你設置的每一個的寬度來自動計算沒行顯示多少個Item 國際慣例,咱們仍是隻介紹一個,那就SliverGridDelegateWithFixedCrossAxisCount吧。
看下代碼,怎麼用
import 'package:flutter/material.dart';
class GridViewPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('GridView'),
),
body: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, //每行2個
mainAxisSpacing: 10.0, //主軸(豎直)方向間距
crossAxisSpacing: 10.0, //縱軸(水平)方向間距
childAspectRatio: 1.0 //縱軸縮放比例
),
children: <Widget>[
Container(
alignment: Alignment.center,
color: Colors.green,
child: Image.asset("images/pic1.jpg"),
),
Container(
alignment: Alignment.center,
color: Colors.green,
child: Image.asset("images/pic1.jpg"),
),
Container(
alignment: Alignment.center,
color: Colors.green,
child: Image.asset("images/pic1.jpg"),
),
Container(
alignment: Alignment.center,
color: Colors.green,
child: Image.asset("images/pic1.jpg"),
),
Container(
alignment: Alignment.center,
color: Colors.green,
child: Image.asset("images/pic1.jpg"),
),
Container(
alignment: Alignment.center,
color: Colors.green,
child: Image.asset("images/pic1.jpg"),
),
Container(
alignment: Alignment.center,
color: Colors.green,
child: Image.asset("images/pic1.jpg"),
),
],
),
);
}
}
複製代碼
和ListView相似,咱們在GridView的children中新增了7個圖片並給它設置背景並居中,另外咱們根據gridDelegate屬性設置每行顯示2個Item,而且設置Item間隔爲10像素。
效果以下: 固然,GridView你也可使用builder()和custom()的方式實現
import 'package:flutter/material.dart';
class GridViewPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return GridViewState();
}
}
class GridViewState extends State<GridViewPage> {
final List<ListItem> listData = [];
@override
void initState() {
super.initState();
for (int i = 0; i < 20; i++) {
listData.add(new ListItem("我是測試標題$i", Icons.cake));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('GridView'),
),
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, //每行2個
mainAxisSpacing: 10.0, //主軸(豎直)方向間距
crossAxisSpacing: 10.0, //縱軸(水平)方向間距
childAspectRatio: 1.0 //縱軸縮放比例
),
itemCount: listData.length,
itemBuilder: (BuildContext context, int index) {
return ListItemWidget(listData[index]);
},
),
);
}
}
class ListItem {
final String title;
final IconData iconData;
ListItem(this.title, this.iconData);
}
class ListItemWidget extends StatelessWidget {
final ListItem listItem;
ListItemWidget(this.listItem);
@override
Widget build(BuildContext context) {
return new GestureDetector(
child: new Container(
color: Colors.green,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Icon(
listItem.iconData,
size: 50.0,
color: Colors.white,
),
new Text(
listItem.title,
style: TextStyle(color: Colors.white),
)
],
),
),
onTap: () {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text(listItem.title),
));
},
);
}
}
複製代碼
和上面ListView的用相似,只不過咱們如今是一行顯示多個Item而已。而且咱們給每一個Item設置上了點擊事件,每次點擊Item就會彈出相應的標題。
##小結
ListView就是咱們經常使用的列表視圖
GridView就是咱們經常使用的宮格視圖
ListView和GridView均可以使用new 或者builder()和custom()方法來建立對象