Flutter進階:深入探究 ListView 和 ScrollPhysics

Meandni發表於1970-01-01

Flutter進階:深入探究 ListView 和 ScrollPhysics

Flutter 中的 ListView 可以對比 Android 中的 ListView 或者 RecycleView(當然也有不同之處) ,是可滾動項的線性列表。 我們可以用它來製作可滾動專案列表或重複專案列表。

探究各型別的 ListView

構建 ListView 有以下幾種方式:

  1. ListView
  2. ListView.builder
  3. ListView.separated
  4. ListView.custom

ListView

這是 ListView 類的預設建構函式。 ListView 內有任意個數的子元素都可使其滾動。

程式碼的格式為:

ListView(
  children: <Widget>[
    ItemOne(),
    ItemTwo(),
    ItemThree(),
  ],
),
複製程式碼

通常這裡應該放少量的子元素,因為 ListView 也會將當前不可見的元素構建起來,因此大量的子元素可能使 App 效能降低。

ListView.builder()

builder() 建構函式可以用來構造重複的子項列表,這裡我們就可以類比 Android 中的 ListView 。 這個建構函式有兩個主要引數:列表中專案數的 itemCount 和構造每個列表子項的 itemBuilder。

/images/listview2.gif

程式碼的格式為:

ListView.builder(
  itemCount: itemCount,
  itemBuilder: (context, position) {
    return listItem();
  },
),
複製程式碼

列表項是懶載入的,這表明 Flutter 只構造了特定數量的列表項,當使用者滾動時,早期的列表項被銷燬。

技巧:由於元素是懶載入的,只載入了所需數量的元素,我們並不需要將 itemCount 作為必需引數,列表可以是無限長的。

ListView.builder(
  itemBuilder: (context, position) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Text(position.toString(), style: TextStyle(fontSize: 22.0),),
      ),
    );
  },
),
複製程式碼

/images/listview3.gif

ListView.separated()

在 separate() 的建構函式中,我們同樣生成一個列表,但這裡我們可以指定每個項之間的分隔符。

/images/listview4.gif

實質上,這裡,我們構造了兩個交織列表:一個作為主列表,一個作為分隔符列表。

要注意的是,這裡不能應用前面建構函式中所說的無限長度,因為此建構函式會強制執行 itemCount 。

程式碼的格式為:

ListView.separated(
      itemBuilder: (context, position) {
        return ListItem();
      },
      separatorBuilder: (context, position) {
        return SeparatorItem();
      },
      itemCount: itemCount,
),
複製程式碼

這種型別的列表允許您動態定義分隔符,為不同型別的子項分配不同型別的分隔符,在需要時新增或刪除分隔符等。

該實現還可以在列表中方便地插入其他型別的子元素(例如廣告),而不需要對列表項中的主列表進行任何修改。

/images/listview5.png

**注意:**通常分隔符列表長度比專案列表小 1,因為在最後一個元素之後不存在分隔符。

ListView.custom()

正如其名,custom() 建構函式允許我們自定義構建 ListViews。 需要的主要引數是 SliverChildDelegate ,用於構建子項。 SliverChildDelegates 的型別是:

  1. verChildListDelegate
  2. SliverChildBuilderDelegate

SliverChildListDelegate 接受一個子項的直接列表,而 SliverChildBuiderDelegate 接受 IndexedWidgetBuilder(我們使用的建構函式)。

您可以使用或子類化這些來構建自己的委託。

ListView 預設建構函式的行為類似於帶有 SliverChildListDelegate 的 ListView.custom 。

我們已經介紹完了 ListViews 的各種型別,讓我們來看看 ScrollPhysics 。

探究 ScrollPhysics

為了控制列表滾動的發生方式,我們在 ListView 的建構函式中通常需要設定 physics 引數。 各種型別的 physics 引數有:

NeverScrollablePhysics

NeverScrollablePhysics 表現為不可滾動的列表。 使用此選項可以完全禁用 ListView 的滾動。

BouncingScrollPhysics

BouncingScrollPhysics 在列表結束時退回列表。 iOS 中有類似的效果。

/images/listview6.gif

ClampingScrollPhysics

這是 Android 上使用的預設滾動方式。 列表在結尾處停止並給出一定的效果。

/images/listview7.gif

FixedExtentScrollPhysics

該方法與其他方法略有不同,因為它僅適用於 FixedExtendScrollControllers 和使用它們的列表。 舉個例子,我們用 ListWheelScrollView 來製作類似輪子的列表。

FixedExtentScrollPhysics 僅滾動到子項而不存在任何偏移。

/images/listview8.gif

樣例程式碼非常簡單:

FixedExtentScrollController fixedExtentScrollController =
    new FixedExtentScrollController();
ListWheelScrollView(
  controller: fixedExtentScrollController,
  physics: FixedExtentScrollPhysics(),
  children: monthsOfTheYear.map((month) {
    return Card(
        child: Row(
      children: <Widget>[
        Expanded(
            child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text(
            month,
            style: TextStyle(fontSize: 18.0),
          ),
        )),
      ],
    ));
  }).toList(),
  itemExtent: 60.0,
),
複製程式碼

你應當知道的其他事情

如何在列表中保留被破壞的元素?

Flutter 提供了一個 KeepAlive() 小元件,它可以使子元素保持活躍狀態,否則會被破壞。 在列表中,預設情況下,元素包裝在 AutomaticKeepAlive 中。

/images/listview9.png

為什麼我的 ListView 在列表和外部小部件之間有空格?

ListView 在它與外部視窗元件之間有預設填充,將填充設定為 EdgeInsets.all(0.0) 就可以刪除它。

最後

利用時間整理分析自己所學的知識是件非常有意義的事情,希望這也能幫到其他正在學習的同學。同時我也正在用Flutter寫幾個專案,寫好之後就會開源給大家。

Github:github.com/MeandNi

微信:yangjk128

部落格:meandni.com/2019/01/26/…

歡迎一起交流移動開發的技術!

參考連結

原英文部落格

官方文件

相關文章