作者 | 弗拉德
來源 | 弗拉德(公眾號:fulade_me)
ListView
ListView是在移動端非常常見的控件,在大多數的展示場景中都離不開ListView。在Flutter中對ListView的封裝也非常好,簡單幾行代碼就可以滿足我們佈局一個滾動列表的需求。
先來看一下構造函數:
ListView({
/// key
Key key,
/// 佈局方向
Axis scrollDirection = Axis.vertical,
/// 是否 倒序顯示
bool reverse = false,
/// ScrollController用於控制滾動位置和監聽滾動事件
ScrollController controller,
/// 是否使用默認的controller
bool primary,
/// 滾動效果 可以通過此參數 設置 ListView 不可滾動
ScrollPhysics physics,
/// 是否根據子控件的總長度來設置ListView的長度,默認值為false
bool shrinkWrap = false,
/// padding
EdgeInsetsGeometry padding,
/// 子控件高度
this.itemExtent,
// 在 關閉屏幕時 是否釋放子控件
bool addAutomaticKeepAlives = true,
/// 是否 避免列表項重繪
bool addRepaintBoundaries = true,
/// 該屬性表示是否把子控件包裝在IndexedSemantics裏,用來提供無障礙語義
bool addSemanticIndexes = true,
// 預加載子控件的個數
double cacheExtent,
/// 子控件數組
List<Widget> children = const <Widget>[],
/// 子控件的個數
int semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
})
builder
Flutter給我們提供了四種構造ListView的方法,有ListView()、ListView.builder()、ListView.separated()、ListView.custom()、
| 構造函數 | 描述 |
|---|---|
| ListView() | 靜態構造方法 初始化之前需要確定數據源的大小 |
| ListView.builder() | 動態構造方法 可動態傳入數據 |
| ListView.separated() | 動態構造方法 可動態傳入數據 可動態定製分割線的樣式 |
| ListView.custom() | 動態構造方法 需要傳入SliverChildDelegate來做動態生成 |
靜態構造方法和動態構造方法
ListView()是初始化的時候需要確定數據源的大小,一旦初始化成功後不能再次動態的插入數據。
ListView.builder()、ListView.separated()、ListView.custom()可以動態的插入數據,且能夠更小的節省內存空間。
我們來看以下代碼:
Flexible(
child: ListView(
children: List.generate(
10,
(index) {
print("without builder index = $index");
return Container(
height: 60,
child: Card(
color: Colors.blue,
child: Center(child: Text("$index")),
),
);
},
),
),
),
Flexible(
child: ListView.builder(
itemCount: 10,
itemExtent: 60,
itemBuilder: (BuildContext contenxt, int index) {
print("builder index = $index");
return Container(
height: 60,
child: Card(
color: Colors.red,
child: Center(child: Text("$index")),
),
);
},
),
),
同樣是需要初始化10個子控件,我們分別在List.generate方法和itemBuilder方法中做了打印操作
輸出如下:
flutter: without builder index = 0
flutter: without builder index = 1
flutter: without builder index = 2
flutter: without builder index = 3
flutter: without builder index = 4
flutter: without builder index = 5
flutter: without builder index = 6
flutter: without builder index = 7
flutter: without builder index = 8
flutter: without builder index = 9
flutter: builder index = 0
flutter: builder index = 1
flutter: builder index = 2
flutter: builder index = 3
flutter: builder index = 4
flutter: builder index = 5
flutter: builder index = 6
flutter: builder index = 7
由輸出的log可見,builder方法只初始化了7個子控件,ListView()方法完整的初始化了10個子控件。
builder方法是在需要使用的時候才會初始化,當頁面滾動到第9個子控件的時候,這個時候才會初始化第9個子控件。
這樣做的優勢是:當我們的列表數據量很大的時候(比如説有成百上千個數據),我們只初始化幾個來滿足頁面的顯示需求,其他的控件在需要的時候,再做初始化這樣就大大的幫助我們節省內存空間。
scrollDirection
ListView同時具備了水平佈局和垂直佈局的能力,我們只需要給scrollDirection設置不同的參數即可。
scrollDirection接收的參數值有兩個Axis.vertical和Axis.horizontal
Axis.vertical
效果如下
Axis.horizontal
效果如下
reverse
參數reverse可以控制列表是按正序顯示還是倒序顯示。
reverse = true
表示倒序顯示
reverse = false
表示正序顯示
physics
某些情況下我們並不想要ListView可以滾動,只要把physics設置為NeverScrollableScrollPhysics即可。
physics還有其他兩個比較重要的值:
ClampingScrollPhysics:在Android設備上有微光效果。
BouncingScrollPhysics:在iOS設備上有彈性效果。
separated
在ListView.separated()構造函數中,我們可以傳入一個自定義的Divider來作作為分隔的樣式
這裏我們來看一下Divider都有哪些參數:
const Divider({
/// key
Key key,
// 高度
this.height,
/// 顏色的 高度
this.thickness,
/// 開頭處的縮進
this.indent,
/// 結束處的縮進
this.endIndent,
/// 顏色
this.color,
})
height = 0
height = 10
thinkness = 10
indent = 100
end = 100
想體驗以上示例的運行效果,可以到我的Github倉庫項目flutter_app->lib->routes->listview_page.dart查看,並且可以下載下來運行並體驗。