Flutter實(shí)戰(zhàn) CustomScrollView

2021-03-08 11:30 更新

CustomScrollView是可以使用 Sliver 來(lái)自定義滾動(dòng)模型(效果)的組件。它可以包含多種滾動(dòng)模型,舉個(gè)例子,假設(shè)有一個(gè)頁(yè)面,頂部需要一個(gè)GridView,底部需要一個(gè)ListView,而要求整個(gè)頁(yè)面的滑動(dòng)效果是統(tǒng)一的,即它們看起來(lái)是一個(gè)整體。如果使用GridView+ListView來(lái)實(shí)現(xiàn)的話(huà),就不能保證一致的滑動(dòng)效果,因?yàn)樗鼈兊臐L動(dòng)效果是分離的,所以這時(shí)就需要一個(gè)"膠水",把這些彼此獨(dú)立的可滾動(dòng)組件"粘"起來(lái),而CustomScrollView的功能就相當(dāng)于“膠水”。

#可滾動(dòng)組件的Sliver版

Sliver 在前面講過(guò),有細(xì)片、薄片之意,在 Flutter 中,Sliver 通常指可滾動(dòng)組件子元素(就像一個(gè)個(gè)薄片一樣)。但是在CustomScrollView中,需要粘起來(lái)的可滾動(dòng)組件就是CustomScrollView的Sliver了,如果直接將ListView、GridView作為CustomScrollView是不行的,因?yàn)樗鼈儽旧硎强蓾L動(dòng)組件而并不是 Sliver!因此,為了能讓可滾動(dòng)組件能和CustomScrollView配合使用,F(xiàn)lutter 提供了一些可滾動(dòng)組件的 Sliver 版,如 SliverList、SliverGrid 等。實(shí)際上 Sliver 版的可滾動(dòng)組件和非Sliver版的可滾動(dòng)組件最大的區(qū)別就是前者不包含滾動(dòng)模型(自身不能再滾動(dòng)),而后者包含滾動(dòng)模型 ,也正因如此,CustomScrollView才可以將多個(gè) Sliver"粘"在一起,這些 Sliver 共用CustomScrollViewScrollable,所以最終才實(shí)現(xiàn)了統(tǒng)一的滑動(dòng)效果。

Sliver 系列 Widget 比較多,我們不會(huì)一一介紹,讀者只需記住它的特點(diǎn),需要時(shí)再去查看文檔即可。上面之所以說(shuō)“大多數(shù)”Sliver 都和可滾動(dòng)組件對(duì)應(yīng),是由于還有一些如 SliverPadding、 SliverAppBar 等是和可滾動(dòng)組件無(wú)關(guān)的,它們主要是為了結(jié)合 CustomScrollView 一起使用,這是因?yàn)?strong>CustomScrollView 的子組件必須都是 Sliver。

#示例

import 'package:flutter/material.dart';


class CustomScrollViewTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //因?yàn)楸韭酚蓻](méi)有使用Scaffold,為了讓子級(jí)Widget(如Text)使用
    //Material Design 默認(rèn)的樣式風(fēng)格,我們使用Material作為本路由的根。
    return Material(
      child: CustomScrollView(
        slivers: <Widget>[
          //AppBar,包含一個(gè)導(dǎo)航欄
          SliverAppBar(
            pinned: true,
            expandedHeight: 250.0,
            flexibleSpace: FlexibleSpaceBar(
              title: const Text('Demo'),
              background: Image.asset(
                "./images/avatar.png", fit: BoxFit.cover,),
            ),
          ),


          SliverPadding(
            padding: const EdgeInsets.all(8.0),
            sliver: new SliverGrid( //Grid
              gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2, //Grid按兩列顯示
                mainAxisSpacing: 10.0,
                crossAxisSpacing: 10.0,
                childAspectRatio: 4.0,
              ),
              delegate: new SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                  //創(chuàng)建子widget      
                  return new Container(
                    alignment: Alignment.center,
                    color: Colors.cyan[100 * (index % 9)],
                    child: new Text('grid item $index'),
                  );
                },
                childCount: 20,
              ),
            ),
          ),
          //List
          new SliverFixedExtentList(
            itemExtent: 50.0,
            delegate: new SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                  //創(chuàng)建列表項(xiàng)      
                  return new Container(
                    alignment: Alignment.center,
                    color: Colors.lightBlue[100 * (index % 9)],
                    child: new Text('list item $index'),
                  );
                },
                childCount: 50 //50個(gè)列表項(xiàng)
            ),
          ),
        ],
      ),
    );
  }
}

代碼分為三部分:

  • 頭部SliverAppBarSliverAppBar對(duì)應(yīng)AppBar,兩者不同之處在于SliverAppBar可以集成到CustomScrollViewSliverAppBar可以結(jié)合FlexibleSpaceBar實(shí)現(xiàn) Material Design 中頭部伸縮的模型,具體效果,讀者可以運(yùn)行該示例查看。
  • 中間的SliverGrid:它用SliverPadding包裹以給SliverGrid添加補(bǔ)白。SliverGrid是一個(gè)兩列,寬高比為4的網(wǎng)格,它有20個(gè)子組件。
  • 底部SliverFixedExtentList:它是一個(gè)所有子元素高度都為50像素的列表。

運(yùn)行效果如圖:

圖6-12

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)