問題
目錄
1:ListView默認構造方法
2:ListView.builder
3:ListView.separated
4: ListTile
預備
正文
ListView 列表
1:ListView默認構造方法
ListView({ //可滾動widget公共參數 Key key, Axis scrollDirection = Axis.vertical, //設置滑動方向 Axis.horizontal 水平 默認 Axis.vertical 垂直 bool reverse = false, //是否倒序顯示 默認正序 false 倒序true ScrollController controller, //滑動監聽 bool primary, //false,如果內容不足,則用戶無法滾動 而如果[primary]為true,它們總是可以嘗試滾動。 ScrollPhysics physics, //滑動類型設置:physics: new ClampingScrollPhysics(), bool shrinkWrap = false, //內容適配 EdgeInsetsGeometry padding, //內間距:padding: EdgeInsets.all(10.0), //ListView各個構造函數的共同參數 this.itemExtent, //確定每一個item的高度 會讓item加載更加高效 bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, double cacheExtent, //設置預加載的區域 //子widget列表 List<Widget> children = const <Widget>[], int semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
1:scrollDirection :滾動方向。默認是vertical,垂直滾動。
2:reverse:是否與設置的滾動方向相反的方向滾動。默認是 false
3:controller:
滑動監聽,我們多用於上拉加載更多,通過監聽滑動的距離來執行操作。
此屬性接受一個ScrollController對象。ScrollController的主要作用是控制滾動位置和監聽滾動事件。
默認情況下,Widget樹中會有一個默認的PrimaryScrollController,
如果子樹中的可滾動組件沒有顯式的指定controller,
並且primary屬性值為true時(默認就為true),可滾動組件會使用這個默認的PrimaryScrollController。
這種機制帶來的好處是父組件可以控制子樹中可滾動組件的滾動行為,
例如,Scaffold正是使用這種機制在iOS中實現了點擊導航欄回到頂部的功能。
4. primary:
否使用widget樹中默認的PrimaryScrollController;
當滑動方向為垂直方向(scrollDirection值為Axis.vertical)並且沒有指定controller時,
primary默認為true.
在構造中默認是false 它的意思就是為主的意思,primary為true時,我們的controller 滑動監聽就不能使用了
5. physics:
此屬性接受一個ScrollPhysics類型的對象,它決定可滾動組件如何響應用戶操作,
比如用戶滑動完抬起手指后,繼續執行動畫;或者滑動到邊界時,如何顯示。
默認情況下,Flutter會根據具體平台分別使用不同的ScrollPhysics對象,
應用不同的顯示效果,如當滑動到邊界時,繼續拖動的話,在iOS上會出現彈性效果,
而在Android上會出現微光效果。如果你想在所有平台下使用同一種效果,
可以顯式指定一個固定的ScrollPhysics,Flutter SDK中包含了兩個ScrollPhysics的子類,
他們可以直接使用:
這個屬性幾個滑動的選擇
AlwaysScrollableScrollPhysics() 總是可以滑動
NeverScrollableScrollPhysics 禁止滾動
BouncingScrollPhysics 內容超過一屏 上拉有回彈效果(iOS下彈性效果)
ClampingScrollPhysics 包裹內容 不會有回彈(Android下微光效果)
6:shrinkWrap:
該屬性表示是否根據子組件的總長度來設置ListView的長度,默認值為false 。
默認情況下,ListView的會在滾動方向盡可能多的占用空間。
當ListView在一個無邊界(滾動方向上)的容器中時,shrinkWrap必須為true。
child 高度會適配 item填充的內容的高度,我們非常的不希望child的高度固定,
因為這樣的話,如果里面的內容超出就會造成布局的溢出。
shrinkWrap多用於嵌套listView中 內容大小不確定 比如 垂直布局中 先后放入文字 listView
(需要Expend包裹否則無法顯示無窮大高度
但是需要確定listview高度 shrinkWrap使用內容適配不會有這樣的影響)
7. padding:
ListView的內邊距。padding: const EdgeInsets.all(16.0),
8. itemExtent:
該參數如果不為null,則會強制children的“長度”為itemExtent的值;
這里的“長度”是指滾動方向上子組件的長度,也就是說如果滾動方向是垂直方向,
則itemExtent代表子組件的高度;如果滾動方向為水平方向,則itemExtent就代表子組件的寬度。
在ListView中,指定itemExtent比讓子組件自己決定自身長度會更高效,這是因為指定itemExtent后,
滾動系統可以提前知道列表的長度,而無需每次構建子組件時都去再計算一下,
尤其是在滾動位置頻繁變化時(滾動系統需要頻繁去計算列表高度)。
9. addAutomaticKeepAlives:
該屬性表示是否將列表項(子組件)包裹在AutomaticKeepAlive 組件中;
典型地,在一個懶加載列表中,如果將列表項包裹在AutomaticKeepAlive中,
在該列表項滑出視口時它也不會被GC(垃圾回收),它會使用KeepAliveNotification來保存其狀態。
如果列表項自己維護其KeepAlive狀態,那么此參數必須置為false。
10. addRepaintBoundaries:
該屬性表示是否將列表項(子組件)包裹在RepaintBoundary組件中。
當可滾動組件滾動時,將列表項包裹在RepaintBoundary中可以避免列表項重繪,
但是當列表項重繪的開銷非常小(如一個顏色塊,或者一個較短的文本)時,
不添加RepaintBoundary反而會更高效。和addAutomaticKeepAlive一樣,
如果列表項自己維護其KeepAlive狀態,那么此參數必須置為false。
11. cacheExtent:
這個屬性的意思就是預加載的區域 設置預加載的區域 cacheExtent 強制設置為了 0.0,從而關閉了“預加載”
二、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, int itemCount,//item 數量 bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, double cacheExtent, int semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, })
1. itemBuilder:
它是列表項的構建器,類型為IndexedWidgetBuilder,返回值為一個widget。
當列表滾動到具體的index位置時,會調用該構建器構建列表項。
2. itemCount:
列表項的數量,如果為null,則為無限列表。
import 'package:flutter/material.dart'; class LearnListView extends StatefulWidget{ @override State<StatefulWidget> createState() { return new _LearnListView(); } } class _LearnListView extends State<StatefulWidget>{ final List<int> data=[]; @override void initState() { // TODO: implement initState super.initState(); for(int i=0;i<100;i++){ data.add(i); } } @override Widget build(BuildContext context) { return new Scaffold( body: new ListView.builder( itemBuilder: (BuildContext context, int index) { int itemDat=data[index]; return new Row( children: <Widget>[ new Container( child:new Image.network( 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=15335368' '41326&di=682e2e7c3810ac92be325e62e173c0ea&imgtype=0&src=http%3A%2F%2Fs6.si' 'naimg.cn%2Fmw690%2F006LDoUHzy7auXEaYER25%26690', width: 100.0, height: 70.0, fit: BoxFit.cover, ), margin: EdgeInsets.all(10.0), ), new Expanded( child:new Column( children: <Widget>[ new Container( height: 70.0, child: new Text('這是一張非常漂亮的美女圖$itemDat,喜歡就趕緊來欣賞吧,等着你哦'), ), ], ), flex: 1, ), ], ); }, itemCount:data.length , ), ); } }
三、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, ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, })
ListView getListViewThree () { return ListView.separated( itemBuilder: (context, index) => ListTile( title: Text('標題$index'), subtitle: Text('副標題$index'), trailing: Icon(Icons.keyboard_arrow_right), isThreeLine: false, dense: false, contentPadding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0), enabled: true, onTap: (){ print('tap'); }, onLongPress: () { print('longPress'); }, selected: index.isEven ? true : false, leading: CircleAvatar( backgroundImage: NetworkImage('http://pic31.nipic.com/20130710/12018626_110428606000_2.jpg') ), ), padding: EdgeInsets.symmetric(vertical: 0.0, horizontal: 15.0), separatorBuilder: (context, index) => Divider( color: Colors.grey[400], height: 1.0, thickness: 1.0, ), itemCount: 20, ); }
四、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, //是否選中狀態 })
import 'package:flutter/material.dart'; class ListViewDemo extends StatelessWidget{ @override Widget build(BuildContext context) { // TODO: implement build return getListViewOne(); } ListView getListViewOne () { return ListView( children: getList(20) ); } List<Widget> getList (int length) { List<Widget> list = List(); for (int i = 0; i < length; i++) { list.add(ListTile( title: Text('標題$i'), subtitle: Text('副標題$i'), trailing: Icon(Icons.keyboard_arrow_right), isThreeLine: false, dense: false, contentPadding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0), enabled: true, onTap: (){ print('tap'); }, onLongPress: () { print('longPress'); }, selected: i.isEven ? true : false, leading: CircleAvatar( backgroundImage: NetworkImage('http://pic31.nipic.com/20130710/12018626_110428606000_2.jpg') ), )); } return list; } }
注意
