Flutter學習總結(十五、Flutter列表)

Flutter列表

一起從0開始學習Flutter!

基本上的組件學的差不多了,我們開始一起來學習日常用的最多的列表功能。列表我們一般常用的有ScrollView,ListView,和GridView,在Flutter中也是有一一對應的組件,在Flutter裏ScrollView是抽象類無法直接被實例化,我們可以使用它的子類,如NestedScrollView,BoxScrollView,在Flutter比較特殊ListView,GridView也是ScrollView的子類。我們依次看下。

1.NestedScrollView

這裏的NestedScrollView跟Android中的意義不一樣,在Android中是直接一個可以滑動的列表,我們將子View放到ScrollView下的ViewGroup中就可以實現一個頁面的滾動,而這裏的NestedScrollView是做了一個包含TabBar的一個封裝,我們可以利用它輕鬆的實現向上滑動的時候頂部的摺疊。

const NestedScrollView({
    Key key,
    this.controller,//滾動操作的控制器,給我們一個默認值_NestedScrollController,如果需要修改可以模仿來做更改
    this.scrollDirection = Axis.vertical, //滾動的方向,Axis.vertical豎向滾動,horizontal橫向滾動
    this.reverse = false,//是否頁面做翻轉,如果是True則bar在下面,滾動的在上面
    this.physics,//當用戶停止滑動,滑動到頂部時的動作
    @required this.headerSliverBuilder,//參照下面的詳細說明
    @required this.body,//參照下面的詳細說明
    this.dragStartBehavior = DragStartBehavior.start,//拖拽開始的狀態
  })

headerSliverBuilder
向上滑動的時候的摺疊區域,可以傳入一組的控件 List,如果我們在向上滑動的時候可以摺疊的話我們需要返回一個SliverOverlapAbsorber,SliverOverlapAbsorber稍後我們做詳細解釋。
body
傳入一個可以滑動的佈局,比如我們可以傳入一個CustomScrollView,我們則可以通過CustomScrollView來實現頁面的滑動,也可以傳入SliverList,SliverGrid讓頁面滾動起來。
先來看下上面提到的SliverOverlapAbsorber。

2.SliverOverlapAbsorber

使用SliverOverlapAbsorber包裹SliverAppBar讓在滑動的時候可以進行通知頭部,控制AppBar的收放。還是先看下構造函數:

const SliverOverlapAbsorber({
    Key key,
    @required this.handle, //參照下面的詳細說明
    Widget child,//需要控制的組件,一般使用SliverAppBar
  })

handle
作爲一個必選參數來控制堆疊時的控件高度,我們一般使用下面NestedScrollView.sliverOverlapAbsorberHandleFor來創建一個默認的操作。

handle:NestedScrollView.sliverOverlapAbsorberHandleFor(context)

3.SliverAppBar

跟AppBar有很多共通的參數,我們可以拿出來它與AppBar的不同之處來作解釋:

const SliverAppBar({
    Key key,
    this.flexibleSpace,//我們需要顯示的標題欄裏的內容,可以根據需要進行自己的設置,比如一個Text
    this.forceElevated = false,//是否保留SliverAppBar下面的陰影,True不管是滾動還是停止都有陰影,False則都不顯示
    this.expandedHeight,//標題欄和文字說明直接的間距
    this.floating = false,//和snap配合使用
    this.pinned = false,//頂部的Title欄是否是固定的,False則不顯示title欄,True則會滑動時保留title欄
    this.snap = false,//和floating配合使用,兩個都是True則滑動到頂再下向滑動時首先是標題欄先滑下來,然後再是列表的向下滾動。
    this.stretch = false,//是否拉伸以充滿滑動區域,沒有試出來它的效果
    this.stretchTriggerOffset = 100.0,//設定調用onStretchTrigger的滑動距離
    this.onStretchTrigger,//設定的回調
    ...
  })

設置還是比較簡單,可以根據我們是否需要滾動,是否滾動的時候是否固定頭部來進行設置。

4.ListView

作爲一個線性排布所有子控件的容器,它其實比較像在Android中認識的ScrollView,但是我們可以通過itemBuilder來實現Android中的ListView的形式。先看下ListView的構造方法,先省略NestedScrollView裏面共通的參數:

ListView({
    Key key,
    bool shrinkWrap = false,//是否根據子組件的總長度來設置ScrollView的長度,如果ScrollView的父容器是一個無邊際的的容器則設置爲True。
    EdgeInsetsGeometry padding,//設置ListView的內填充大小
    this.itemExtent,//如果不爲空則會強制children的長度爲itemExtent的值。
    bool addAutomaticKeepAlives = true,//是否將列表項放到AutomaticKeepAlive組件中,在懶加載的時候如果設置爲True則滑出窗口視圖的時候不會被回收,由KeepAliveNotification來保存狀態
    bool addRepaintBoundaries = true,//是否將列表項放到RepaintBoundary組件中,設置爲True在列表滾動的時候可以避免重繪,但是如果每個Item都很簡單比較小的時候如果設置爲True會更高效。
    bool addSemanticIndexes = true,//設置是否將列表項添加到用位置來表示的語義控件中,還是原來說到的輔助功能使用的
    double cacheExtent,//緩存的長度
    List<Widget> children = const <Widget>[],//參照下面的詳細說明
    int semanticChildCount,//語義表達的列表項的數量,還是輔助功能使用。
    ...
  })

children
這裏用來存放滑動的內容,我們可以創建一組Text爲了測試滑動比如:

ListView(
          children: <Widget>[
            Text("Hello"),
            Text("Hello"),
            Text("Hello"),
            Text("Hello"),
          ],
        )

如果要是顯示一組內容相同的列表我們可以使用ListView的建造者模式的方法ListView.builder(),其他的參數同ListView只是多了一個

 @required IndexedWidgetBuilder itemBuilder,

我們可以通過它來創建一組數據的列表比如:

ListView.builder(
          itemBuilder: (BuildContext context, int index) {
            return Text("Hello" + index.toString());
          },
          padding: EdgeInsets.all(30),
        )

常用的還有ListView.separated()只是比ListView.builder()多了一個分割線的設置,不再贅述,可以自己試一下。

5.GridView

跟ListView的參數有很大的相似度,它的功能就是將豎向列表在橫向也可以按照指定的塊數顯示。我們看下它的構造方法,跟ListView類似的不再說明:

GridView({
    Key key,
    @required this.gridDelegate,//參照下面的詳細說明
   ...
  })

gridDelegate
我們看到需要傳入一個SliverGridDelegate,但是該類是一個抽象類,我們需要傳入一個實現類,找到了SliverGridDelegateWithFixedCrossAxisCount,我們將其傳入,來看下它有哪些參數

const SliverGridDelegateWithFixedCrossAxisCount({
    @required this.crossAxisCount,//要劃分的塊數
    this.mainAxisSpacing = 0.0,//跟主要滑動方向一致的每塊間隔大小
    this.crossAxisSpacing = 0.0,//另外一個方向上每塊間隔大小
    this.childAspectRatio = 1.0,//滑動方向和另一方向塊的大小比例
  })

一個簡單的使用:

GridView(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount:3,
              mainAxisSpacing:10,
            crossAxisSpacing: 10,
          ),
          children: <Widget>[
            Text("Hello",style: TextStyle(backgroundColor: Colors.green),),
            Text("Hello"),
            Text("Hello"),
            Text("Hello"),
          ],
        ),

在GridView中也有builder()和separated()方法,跟ListView的方法一致。

6.SliverList

可以理解爲我們可以將多個佈局按照一個順序來進行的排列,每個都是單獨的個體。它的構造比較簡單,我們看下:

const SliverList({
    Key key,
    @required SliverChildDelegate delegate,//參照下面的詳細說明
  })

delegate
就只需要傳入一個代理,SliverChildDelegate是一個抽象類,我們還需要找到它的實現SliverChildListDelegate,來看下SliverChildListDelegate的構造:

SliverChildListDelegate(
    this.children, {
    this.addAutomaticKeepAlives = true,
    this.addRepaintBoundaries = true,
    this.addSemanticIndexes = true,
    this.semanticIndexCallback = _kDefaultSemanticIndexCallback,
    this.semanticIndexOffset = 0,
  })

跟List基本上一樣的參數,只是children是一組組件,我們需要一個個的實現,SliverChildDelegate下面還有一個實現是SliverChildBuilderDelegate,這個可以幫助我們快速的創建一組列表與ListView相同的略過:

const SliverChildBuilderDelegate(
    this.builder, //這裏創建了一個構造器,下面詳細說明
	{this.findChildIndexCallback,//構造一個返回當前Item的Index的方法
    this.childCount,//想要顯示的Item的數量
    ...
  })

builder
可以看到它的定義是比較有意思的,是定義了一個方法:

typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index);

我們需要傳一個函數進去,可以簡單的試一下:

delegate: SliverChildBuilderDelegate(
                        (BuildContext context, int index) {
                      return Container(
                        alignment: Alignment.center,
                        color: Colors.red,
                        child: Text("position is $index",style: TextStyle(fontSize: 14,color: Colors.black),),
                      );
                    }
                )

這樣就構造了一個我想要顯示的每一個條目的樣式,然後控制數量和緩存機制就可以了。

7.SliverGrid

跟GridView是一樣的顯示形式,只是也是進行了分塊,我們還是看下構造方法:

  const SliverGrid({
    Key key,
    @required SliverChildDelegate delegate,
    @required this.gridDelegate,
  })

只是比上面的SliverList多了一個gridDelegate,我們只看下gridDelegate,看到它需要傳入SliverGridDelegate,但是也是一個抽象類,還是看下它的實現SliverGridDelegateWithFixedCrossAxisCount,嗯,是的,跟GridView中的是一樣的,我們可以直接去看GridView中的說明。這樣進行設置後一個可以分割的Grid就完成了。

8.CustomScrollView

跟ScrollView也不是一樣的,它比較像是一個粘合劑的作用,如果我們的列表顯示多個列表的組合那麼可以放置到CustomScrollView裏面,來保證它們的滑動事件的統一,裏面也可以放置像ListView和GridView這樣子的組件,但是需要注意如果我們需要讓他們聯合滾動需要不能使用ListView和GridView,我們需要一種已經幫我們做好分割的SliverList和SliverGrid,還是先看下他的構造方法,有部分同NestedScrollView直接去掉了:

const CustomScrollView({
    Key key,
    bool primary,//如果爲True則會讓它的Controller創建一個PrimaryScrollController的實體,不能再自定義Controller。
    bool shrinkWrap = false,//是否根據子組件的總長度來設置ScrollView的長度,如果ScrollView的父容器是一個無邊際的的容器則設置爲True。
    Key center,
    this.slivers = const <Widget>[],//參照下面的詳細說明
    ...
  })

slivers
這裏我們就要放入可分裂的組件了,我們可以將上面的SliverList或者SliverGrid放入其中,可以混合放入,這樣就成了一個混合列表。
滾動頁面的內容比較複雜,不是很好理解,還是建議多去試一試,這樣可以加深我們的記憶。

接下來我們一起來學習Flutter中的頁面跳轉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章