flutter系列之:使用SliverList和SliverGird 簡介 SliverList和SliverGird詳解 SliverList和SliverGird的使用 總結

簡介

在上一篇文章我們講解SliverAppBar的時候有提到過,Sliver的組件一般都用在CustomScrollView中。除了SliverAppBar之外,我們還可以爲CustomScrollView添加List或者Grid來實現更加複雜的組合效果。

今天要向大家介紹的就是SliverList和SliverGird。

SliverList和SliverGird詳解

從名字就可以看出SliverList和SliverGird分別是List和Grid的一種,他們和List與Grid最大的區別在於,他們可以控制子widget在main axis和cross axis之間的間隔,並且可以通過Extent屬性來控制子widget的大小,非常的強大。

我們先來看下這兩個組件的定義和構造函數:

class SliverList extends SliverMultiBoxAdaptorWidget {
  /// Creates a sliver that places box children in a linear array.
  const SliverList({
    Key? key,
    required SliverChildDelegate delegate,
  }) : super(key: key, delegate: delegate);

SliverList繼承自SliverMultiBoxAdaptorWidget,它的構造函數比較簡單,需要傳入一個SliverChildDelegate的參數,這裏的SliverChildDelegate使用的是delegate的方法來創建SliverList的子組件。

SliverChildDelegate是一個抽象類,它有兩個實現類,分別是SliverChildBuilderDelegate和SliverChildListDelegate。

其中SliverChildBuilderDelegate是用的builder模式來生成子widget,在上一篇文章中,我們構建SliverList就是使用的這個builder類。

SliverChildBuilderDelegate使用builder來生成子Widget,而SliverChildListDelegate需要傳入一個childList來完成構造,也就是說SliverChildListDelegate需要一個確切的childList,而不是用builder來構建。

要注意的是SliverList並不能指定子widget的extent大小,如果你想指定List中的子widget的extent大小的話,那麼可以使用SliverFixedExtentList:

class SliverFixedExtentList extends SliverMultiBoxAdaptorWidget {
  const SliverFixedExtentList({
    Key? key,
    required SliverChildDelegate delegate,
    required this.itemExtent,
  }) : super(key: key, delegate: delegate);

可以看到SliverFixedExtentList和SliverList相比,多了一個itemExtent參數,用來控制子widget在main axis上的大小。

然後我們再來看一下SliverGird:

class SliverGrid extends SliverMultiBoxAdaptorWidget {
  /// Creates a sliver that places multiple box children in a two dimensional
  /// arrangement.
  const SliverGrid({
    Key? key,
    required SliverChildDelegate delegate,
    required this.gridDelegate,
  }) : super(key: key, delegate: delegate);

SliverGrid也是繼承自SliverMultiBoxAdaptorWidget,和SliverList一樣,它也有一個SliverChildDelegate的參數,另外它還多了一個gridDelegate的參數用來控制gird的佈局。

這裏的gridDelegate是一個SliverGridDelegate類型的參數,用來控制children的size和position。

SliverGridDelegate也是一個抽象類,它有兩個實現類,分別是SliverGridDelegateWithMaxCrossAxisExtent和SliverGridDelegateWithFixedCrossAxisCount,這兩個實現類的區別就在於MaxCrossAxisExtent和FixedCrossAxisCount的區別。

怎麼理解MaxCrossAxisExtent呢?比如說這個Grid是豎向的,然後Gird的寬度是500.0,如果MaxCrossAxisExtent=100,那麼delegate將會創建5個column,每個column的寬度是100。

crossAxisCount則是直接指定cross axis的child個數有多少。

SliverList和SliverGird的使用

有了上面介紹的SliverList和SliverGird的構造函數,接下來我們具體來看下如何在項目中使用SliverList和SliverGird。

默認情況下SliverList和SliverGird是需要和CustomScrollView一起使用的,所以我們先創建一個CustomScrollView,在它的slivers屬性中,放入一個SliverAppBar組件:

CustomScrollView(
      slivers: <Widget>[
        const SliverAppBar(
          pinned: true,
          snap: false,
          floating: false,
          expandedHeight: 200.0,
          flexibleSpace: FlexibleSpaceBar(
            title: Text('SliverList and SliverGrid'),
          ),
        ),
      ],
    );

SliverAppBar只是一個AppBar,運行可以得到下面的界面:

我們還需要爲它繼續添加其他的slivers組件。

首先給他添加一個SliverGrid:

SliverGrid(
          gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
            maxCrossAxisExtent: 200.0,
            mainAxisSpacing: 20.0,
            crossAxisSpacing: 50.0,
            childAspectRatio: 4.0,
          ),
          delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
              return Container(
                alignment: Alignment.center,
                color: Colors.green[100 * (index % 9)],
                child: Text('grid item $index'),
              );
            },
            childCount: 20,
          ),
        ),

這裏我們設置了gridDelegate屬性,並且自定義了SliverChildBuilderDelegate,用來生成20個Container。

運行得到的界面如下:

然後爲其添加SliverList:

SliverList(
          delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
              return Container(
                color: index.isOdd ? Colors.white : Colors.green,
                height: 50.0,
                child: Center(
                  child: ListTile(
                    title: Text(
                      '100' + index.toString(),
                      style: const TextStyle(fontWeight: FontWeight.w500),
                    ),
                    leading: Icon(
                      Icons.account_box,
                      color: Colors.green[100 * (index % 9)],
                    ),
                  ),
                ),
              );
            },
            childCount: 15,
          ),
        ),

因爲SliverList只需要傳入一個delegate參數,這裏我們生成了15個child組件。生成的界面如下:

因爲SliverList不能控制List中子widget的extent,所以我們再添加一個SliverFixedExtentList看看效果:

SliverFixedExtentList(
          itemExtent: 100.0,
          delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
              return Container(
                color: index.isOdd ? Colors.white : Colors.green,
                height: 50.0,
                child: Center(
                  child: ListTile(
                    title: Text(
                      '200' + index.toString(),
                      style: const TextStyle(fontWeight: FontWeight.w500),
                    ),
                    leading: Icon(
                      Icons.account_box,
                      color: Colors.green[100 * (index % 9)],
                    ),
                  ),
                ),
              );
            },
            childCount: 15,
          ),

SliverFixedExtentList和SliverList相比多了一個itemExtent屬性,這裏我們將其設置爲100,運行可以得到下面的界面:

可以看到List中的子Widget高度發生了變化。

總結

在CustomScrollView中使用SliverList和SliverGird,可以實現靈活的呈現效果。

本文的例子:https://github.com/ddean2009/learn-flutter.git

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