在我們開發(fā)App的時,最常用的就是列表,在flutter中使用ListView來實現(xiàn)類表的功能.
1.ListView使用方法
1.1 ListView()
ListView的創(chuàng)建方法是直接調(diào)用其默認的構(gòu)造函數(shù)來創(chuàng)建列表.
下面我們就來看下其構(gòu)造函數(shù):
ListView({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
this.itemExtent,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
int semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.down,
})
- key:做一個標志來使用,相當于iOS中的tag;
- scrollDirection:列表的滾動方向斧蜕,可選值有Axis的horizontal和vertical示辈,可以看到默認是垂直方向上滾動;
- reverse:是一個bool值,選擇是否翻轉(zhuǎn);
- controller:控制器,處理與列表滾動相關(guān)的,比如監(jiān)聽列表的滾動的事件,滾動的位置;
- physics: 列表滾動至邊緣后繼續(xù)拖動的物理效果,Android與iOS效果不同。Android會呈現(xiàn)出一個波紋狀(對應(yīng)ClampingScrollPhysics)深纲,而iOS上有一個回彈的彈性效果(對應(yīng)BouncingScrollPhysics)浸卦。如果你想不同的平臺上呈現(xiàn)各自的效果可以使用AlwaysScrollableScrollPhysics拓型,它會根據(jù)不同平臺自動選用各自的物理效果鞍匾。如果你想禁用在邊緣的拖動效果,那可以使用NeverScrollableScrollPhysics;
- shrinkWrap: 該屬性將決定列表的長度是否僅包裹其內(nèi)容的長度愧哟。當ListView嵌在一個無限長的容器組件中時奥吩,shrinkWrap必須為true,否則Flutter會給出警告;
- padding: 列表內(nèi)邊距蕊梧;
- itemExtent: 子元素長度霞赫。當列表中的每一項長度是固定的情況下可以指定該值,有助于提高列表的性能(因為它可以幫助ListView在未實際渲染子元素之前就計算出每一項元素的位置);
- cacheExtent: 預(yù)渲染區(qū)域長度肥矢,ListView會在其可視區(qū)域的兩邊留一個cacheExtent長度的區(qū)域作為預(yù)渲染區(qū)域(對于ListView.build或ListView.separated構(gòu)造函數(shù)創(chuàng)建的列表端衰,不在可視區(qū)域和預(yù)渲染區(qū)域內(nèi)的子元素不會被創(chuàng)建或會被銷毀);
- children: 容納子元素的組件數(shù)組;
默認的創(chuàng)建模式:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget _getListItem(String title,IconData icon){
return Container(
child: ListTile(
leading: Icon(icon),
trailing: Icon(icon),
title: Text(title),
subtitle: Text('我是將軍'),
),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'textTitle',
home: Scaffold(
appBar: AppBar(
title: Text('最后戰(zhàn)役'),
),
body: Center(
child: ListView(
children: <Widget>[
_getListItem('第一行', Icons.map),
_getListItem('第二行', Icons.phone),
_getListItem('第三行', Icons.adb),
],
),
),
),
);
}
}
1.2 ListTitle()
在上面的代碼部分出現(xiàn)了一個ListTitle,ListTile 是Flutter 給我們準備好的widget 提供非常常見的構(gòu)造和定義方式橄抹,包括文字靴迫,icon,點擊事件楼誓,一般是能夠滿足基本需求玉锌,但是就不能自己定義了.
ListTitle的屬性
this.leading, // item 前置圖標
this.title, // item 標題
this.subtitle, // item 副標題
this.trailing, // item 后置圖標
this.isThreeLine = false, // item 是否三行顯示
this.dense, // item 直觀感受是整體大小
this.contentPadding, // item 內(nèi)容內(nèi)邊距
this.enabled = true,
this.onTap, // item onTap 點擊事件
this.onLongPress, // item onLongPress 長按事件
this.selected = false, // item 是否選中狀態(tài)
1.3 ListView builder()
builder 顧名思義 構(gòu)造 可以非常方便的構(gòu)建我們自己定義的child布局,所以在Flutter中非常的常用疟羹。
builder屬性詳細介紹
//設(shè)置滑動方向 Axis.horizontal 水平 默認 Axis.vertical 垂直
scrollDirection: Axis.vertical,
//內(nèi)間距EdgeInsets.all(),EdgeInsets.only().
padding: EdgeInsets.all(10.0),
//是否倒序顯示 默認正序 false 倒序true
reverse: false,
//false主守,如果內(nèi)容不足,則用戶無法滾動 而如果[primary]為true榄融,它們總是可以嘗試滾動参淫。
primary: true,
//確定每一個item的高度 會讓item加載更加高效
itemExtent: 50.0,
//內(nèi)容適配
shrinkWrap: true,
//item 數(shù)量
itemCount: list.length,
//滑動類型設(shè)置
physics: new ClampingScrollPhysics(),
//cacheExtent 設(shè)置預(yù)加載的區(qū)域
cacheExtent: 30.0,
//滑動監(jiān)聽
controller ,
- child 高度會適配 item填充的內(nèi)容的高度,我們非常的不希望child的高度固定,因為這樣的話愧杯,如果里面的內(nèi)容超出就會造成布局的溢出涎才。
- shrinkWrap多用于嵌套listView中 內(nèi)容大小不確定 比如 垂直布局中 先后放入文字 listView (需要Expend包裹否則無法顯示無窮大高度 但是需要確定listview高度 shrinkWrap使用內(nèi)容適配不會有這樣的影響).
- primary在構(gòu)造中默認是false 它的意思就是為主的意思,primary為true時,我們的controller 滑動監(jiān)聽就不能使用了.
- physics這個屬性幾個滑動的選擇:
AlwaysScrollableScrollPhysics() 總是可以滑動
NeverScrollableScrollPhysics禁止?jié)L動
BouncingScrollPhysics 內(nèi)容超過一屏 上拉有回彈效果
ClampingScrollPhysics 包裹內(nèi)容 不會有回彈- cacheExtent這個屬性的意思就是預(yù)加載的區(qū)域,設(shè)置預(yù)加載的區(qū)域 cacheExtent 強制設(shè)置為了 0.0耍铜,從而關(guān)閉了“預(yù)加載”.
- controller滑動監(jiān)聽邑闺,我們多用于上拉加載更多,通過監(jiān)聽滑動的距離來執(zhí)行操作棕兼。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'textTitle',
home: Scaffold(
appBar: AppBar(
title: Text('最后戰(zhàn)役'),
),
body: Container(
child:listViewLayoutBuilder(),
),
),
);
}
}
///listView builder 構(gòu)建
Widget listViewLayoutBuilder() {
return ListView.builder(
scrollDirection: Axis.vertical,
padding: EdgeInsets.all(10.0),
reverse: false,
primary: true,
itemExtent: 50.0,
shrinkWrap: true,
itemCount: 4,
cacheExtent: 30.0,
physics: new ClampingScrollPhysics(),
itemBuilder: (context, i){
return Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Text(
"1",
style: new TextStyle(fontSize: 18.0, color: Colors.red),
),
new Text(
"2",
style: new TextStyle(fontSize: 18.0, color: Colors.green),
),
new Text(
"3",
style: new TextStyle(fontSize: 18.0, color: Colors.blue),
),
],
),
);}
);
}
2.ListView的分割線加入
2.1 builder模式來設(shè)置分割線
我們在正常的需求中大部分是需要item的分割線的陡舅,而在builder模式中使用divide 會有種情況(divide放在item的布局中 通過Column),我們會發(fā)現(xiàn)divide并沒有直接延時到item兩端而是會有左右padding伴挚。
所以我們可以通過另外一種方式去實現(xiàn)靶衍。
//1.擴大list容積 為什么是兩倍,因為我們給了divide的index
Widget listView = new ListView.builder(
itemCount: list.length * 2 ,
itemBuilder: (context, index) => itemDividerRow(context, index));
//2. 根據(jù)下標分配item類型
itemDividerRow(context, int i) {
if (i.isOdd) {//是奇數(shù)
return new Divider( //返回分割線
height: 1.0,
);
} else {
i = i ~/ 2;
return getRowWidget(context, orderList[i]); //返回item 布局
}
}
這樣我們就可以去實現(xiàn)了茎芋,builder模式分割線 .
2.2 ListView separated
ListView.separated的模式更加方便我們給列表頁面添加分割線.
ListView.separated({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
@required IndexedWidgetBuilder itemBuilder,
@required IndexedWidgetBuilder separatorBuilder, //分割線
@required int itemCount,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
})
從屬性大部分可以看出和flutter的ListView屬性差不多.比ListView多了一個separatorBuilder的屬性.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'textTitle',
home: Scaffold(
appBar: AppBar(
title: Text('最后戰(zhàn)役'),
),
body: Container(
child: ListViewBuilder(),
),
),
);
}
}
class ListViewBuilder extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ListViewBuilder();
}
}
class _ListViewBuilder extends State<ListViewBuilder> {
/*初始項為50個*/
List<int> indexs = List.generate(50, (index) {
return index;
});
@override
Widget build(BuildContext context) {
/*灰色分割線*/
var divider = Divider(
color: Colors.grey,
);
return ListView.separated(
padding: EdgeInsets.all(10),
itemCount: indexs.length,
separatorBuilder: (context, index) {
return divider;
},
itemBuilder: (context, index) {
/*加載到底部時且集合數(shù)量小于100的話颅眶,獲取更多數(shù)據(jù)*/
if (index == indexs.length - 1 && indexs.length < 100) {
_getMoreData(index);
}
return Text("${index}");
});
}
void _getMoreData(int index) {
Future.delayed(Duration(milliseconds: 300)).then((e) {
setState(() {
/*往集合里添加10條數(shù)據(jù)*/
indexs.addAll(List.generate(10, (i) {
return index + i;
}));
});
});
}
}
想了解更多Flutter學習知識請聯(lián)系:QQ(814299221)