Flutter Sliver滾動組件的演示代碼

Flutter Sliver滾動組件

 SliverList & SliverGrid

需要同時滾動ListView和GridView時可以使用SliverList和SliverGrid。

在這裡插入圖片描述

CustomScrollView(
    slivers: [
        SliverList(
            delegate: SliverChildBuilderDelegate(
                (context, index) {
                    return Container(
                        height: 50,
                        color: Colors.primaries[index % Colors.primaries.length],
                    );
                },
                childCount: 5,
            ),
        ),
        SliverGrid(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
                crossAxisSpacing: 5,
                mainAxisSpacing: 5,
            ),
            delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                    return Container(
                        color: Colors.primaries[index % Colors.primaries.length],
                    );
                },
                childCount: 20,
            ),
        ),
    ],
)

SliverAppBar

pinned:是否固定在屏幕頂部。

expandedHeight:展開區域的高度。

flexibleSpace:展開取消顯示內容。

在這裡插入圖片描述

CustomScrollView(
    slivers: [
        SliverAppBar(
            pinned: true,
            expandedHeight: 200,
            flexibleSpace: FlexibleSpaceBar(
                title: const Text("SliverAppBar"),
                background: Image.asset("images/avatar.jpg", fit: BoxFit.cover),
            ),
        ),
        SliverFixedExtentList(
            delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                    return Container(
                        alignment: Alignment.center,
                        color: Colors.primaries[index % Colors.primaries.length],
                        child: Text("$index"),
                    );
                },
            ),
            itemExtent: 50.0,
        ),
    ],
)

SliverPersistentHeader

SliverPersistentHeader組件可以控制滾動的最大高度和最小高度,類似SliverAppBar效果。

build:顯示內容。

maxExtent & minExtent:滾動的高度范圍。

shouldRebuild:是否需要更新。

在這裡插入圖片描述

CustomScrollView(
    slivers: [
        SliverPersistentHeader(
            pinned: true,
            delegate: MySliverPersistentHeaderDelegate(),
        ),
        SliverGrid(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
                crossAxisSpacing: 5,
                mainAxisSpacing: 5,
            ),
            delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                    return Container(
                        color: Colors.primaries[index % Colors.primaries.length],
                    );
                },
            ),
        ),
    ],
)
class MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
    @override
    Widget build(
        BuildContext context, double shrinkOffset, bool overlapsContent) {
        return Container(
            color: Colors.blue,
            alignment: Alignment.center,
            child: Text(
                "hello world",
                style: TextStyle(color: Colors.white),
            ),
        );
    }

    @override
    double get maxExtent => 200;

    @override
    double get minExtent => 50;

    @override
    bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
        return false;
    }
}

SliverToBoxAdapter

CustomScrollView隻能包含Sliver組件,如果需要使用普通組件可以使用SliverToBoxAdapter。

在這裡插入圖片描述

CustomScrollView(
    slivers: [
        SliverToBoxAdapter(
            child: Container(
                height: 200,
                color: Colors.black26,
                alignment: Alignment.center,
                child: Text("hello world"),
            ),
        ),
        SliverList(
            delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                    return Container(
                        height: 60,
                        color: Colors.primaries[index % Colors.primaries.length],
                    );
                },
                childCount: 50,
            ),
        ),
    ],
)

CustomScrollView & NestedScrollView

CustomScrollView組件可以將多個組件組合在一起,具有統一的滾動效果,但是CustomScrollView隻能嵌套Sliver系列的組件,如SliverList、SliverGrid、SliverPadding、SliverAppBar等。

NestedScrollView可以協調兩個滾動組件滑動。NestedScrollView在邏輯上將可滾動組件分為header和body兩部分,heade部分隻能接收Sliver類型的組件,而body部分可以接收任意類型的組件。

NestedScrollView+SliverAppBar+SliverFixedExtentList+ListView

在這裡插入圖片描述

NestedScrollView(
    //Sliver組件
    headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return [
            SliverAppBar(
                title: const Text("嵌套ListView"),
                pinned: true, //固定AppBar             
                forceElevated: true,
            ),
            SliverFixedExtentList(
                itemExtent: 50,
                delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                        return ListTile(title: Text("$index"));
                    },
                    childCount: 5,
                ),
            ),
        ];
    },
    //滾動組件
    body: ListView.builder(
        padding: const EdgeInsets.all(8),
        physics: const ClampingScrollPhysics(), //需要
        itemCount: 30,
        itemBuilder: (BuildContext context, int index) {
            return SizedBox(
                height: 50,
                child: Center(child: Text("item $index")),
            );
        },
    ),
)

NestedScrollView+SliverAppBar+CustomScrollView

在這裡插入圖片描述

NestedScrollView(
    headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return [
            SliverAppBar(
                floating: true,
                snap: true,
                expandedHeight: 200,
                forceElevated: innerBoxIsScrolled,
                flexibleSpace: FlexibleSpaceBar(
                    background: Image.asset(
                        "images/logo.png",
                        fit: BoxFit.cover,
                    ),
                ),
            ),
        ];
    },
    body: CustomScrollView(
        slivers: [buildSliverList(50)],
    ),
)

優化聯動效果

SliverAppBar+CustomScrollView組合,當反向滑動時,SliverAppBar就會整體回到屏幕頂部,出現遮擋問題,為瞭解決該問題,可以用在header裡用SliverOverlapAbsorber組件包裹SliverAppBar,body裡Sliver列表最前面添加一個SliverOverlapInjector。

NestedScrollView(
    headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return [
            SliverOverlapAbsorber(
                handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                sliver: SliverAppBar(
                    floating: true,
                    snap: true,
                    expandedHeight: 200,
                    forceElevated: innerBoxIsScrolled,
                    flexibleSpace: FlexibleSpaceBar(
                        background: Image.asset(
                            "images/logo.png",
                            fit: BoxFit.cover,
                        ),
                    ),
                ),
            ),
        ];
    },
    body: Builder(
        builder: (BuildContext context) {
            return CustomScrollView(
                slivers: [
                    SliverOverlapInjector(
                        handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                    ),
                    buildSliverList(50),
                ],
            );
        },
    ),
)

NestedScrollView+TabBarView

在這裡插入圖片描述

class MyPageView extends StatefulWidget {
    late List<String> tabs;

    MyPageView({Key? key, required this.tabs}) : super(key: key);

    @override
    State<StatefulWidget> createState() {
        return _MyPageViewState();
    }
}

class _MyPageViewState extends State<MyPageView>
    with SingleTickerProviderStateMixin {
    late TabController _controller;

    @override
    void initState() {
        super.initState();
        _controller = TabController(length: widget.tabs.length, vsync: this);
    }

    @override
    void dispose() {
        super.dispose();
        _controller.dispose();
    }

    @override
    Widget build(BuildContext context) {
        return NestedScrollView(
            headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
                return [
                    SliverOverlapAbsorber(
                        handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                        sliver: SliverAppBar(
                            title: const Text("hi Flutter"),
                            floating: true,
                            snap: true,
                            forceElevated: innerBoxIsScrolled,
                            bottom: TabBar(
                                controller: _controller,
                                tabs: widget.tabs.map((e) => Tab(text: e)).toList(),
                            ),
                        ),
                    ),
                ];
            },
            body: TabBarView(
                controller: _controller,
                children: widget.tabs.map((e) {
                    return Builder(builder: (BuildContext context) {
                        return CustomScrollView(
                            key: PageStorageKey(e),
                            slivers: [
                                SliverOverlapInjector(
                                    handle:
                                    NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                                ),
                                SliverPadding(
                                    padding: const EdgeInsets.all(9),
                                    sliver: buildSliverList(50),
                                ),
                            ],
                        );
                    });
                }).toList(),
            ),
        );
    }
}

到此這篇關於Flutter Sliver滾動組件的文章就介紹到這瞭,更多相關Flutter 滾動組件內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: