Flutter Sliver滚动组件的演示代码

目录
  • Flutter Sliver滚动组件
    • SliverList & SliverGrid
    • SliverAppBar
    • SliverPersistentHeader
    • SliverToBoxAdapter
    • CustomScrollView & NestedScrollView
      • NestedScrollView+SliverAppBar+SliverFixedExtentList+ListView
      • NestedScrollView+SliverAppBar+CustomScrollView
      • 优化联动效果
      • NestedScrollView+TabBarView

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 滚动组件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2021-11-17

android使用flutter的ListView实现滚动列表的示例代码

现如今打开一个 App,比如头条.微博,都会有长列表,随着我们不断地滑动,视窗内的内容也会不断地更新.今天就用 Flutter 实现一下这种效果. 这里的表现其实就相当于有一个固定长度的容器,然后超出的内容是不可见的,只有当你向上或向下滑动屏幕时,视窗外看不见的内容才会出现在视窗中.如果在 web 开发时,是需要容器加上样式 overflow: auto; 要想用 Flutter 实现,其实也是很简单的,因为 Flutter 为我们提供了 ListView 组件. ListView 主要有以下几

Flutter 滚动监听及实战appBar滚动渐变的实现

介绍 在 Flutter 中滚动监听一般可以采用两种方式来实现,分别是ScrollController和NotificationListener这两种方式. ScrollController介绍 ScrollController 介绍一下ScrollController常用的属性和方法: offset:可滚动组件当前的滚动位置. jumpTo(double offset)跳转到指定位置,offset为滚动偏移量. animateTo(double offset,@required Duratio

学习Bootstrap滚动监听 附调用方法

本文为大家介绍Bootstrap滚动监听,供大家学习,具体内容如下 滚动监听 伴随着滚动条的滚动,列表项被不断切换激活 <!-- id="menu" 为data-target="#menu" 的监听对象--> <!-- navbar navbar-inner nav navbar-fixed-top 固定导航条 --> <div id="menu" class="navbar navbar-fixed-to

Bootstrap每天必学之滚动监听

本文为大家介绍Bootstrap滚动监听,供大家学习,具体内容如下 1. Scrollspy currently requires the use of a Bootstrap nav component for proper highlighting of active links. ---- 使用滚动监听的话,导航栏必须采用 class="nav"的nav组件才可以: 下面是源代码中的一段,标红的部分可以证明这一点: 使用ScrollSpy的时候,需要采用<ul class=

jQuery实现可兼容IE6的滚动监听功能

本文实例讲述了jQuery实现可兼容IE6的滚动监听功能.分享给大家供大家参考,具体如下: 其实这东西本打算用原生的javascript来写,但是原生的javascript取class与监听滚动条的滚动过于麻烦,因此上了jQuery,没关系,反正兼容IE6就行. 将实现如下的效果: 也就是在网页中有点常见的滚动监听.相应的标题,滚到哪里,则左边的滚动条当前标题前的...就变成>>>,,当然了,左边的标题同样是可以点击,马上滚到该滚的地方. 首先是网页布局部分,代码如下,请忽略大堆的Jav

jQuery滚动监听实现商城楼梯式导航效果

话不多说,上局部效果图: html结构,左侧定位的导航需要一个ul,中间内容,我是直接截得图片,为了效果省事,也是用的ul,最后你们要用的话也可以用ul,或者div,但是每个区域得是一个div,例如,精选的放一个div,女装的放一个div,所有的区域都套在一个大的div里面,也就是类似于ul>li的结构(只提供html结构和jQuery,样式的话根据设计稿): <div class="menu"> <ul> <li class="on&qu

详解使用vue-router进行页面切换时滚动条位置与滚动监听事件

按照正常的产品逻辑,我们在进行页面切换时滚动条应该是在页面顶部的,可是...在使用vue-router进行页面切换时,发现滚动条所处的位置被自动记录了下来,且在另一个组件内定义的滚动监听事件仍会运行,着实吃了一大惊... 说说我的破解方法: 1.在每个需要用vue-router切换的组件的mounted钩子内将页面的位置自动回滚到页面顶部,解决滚动条位置自动记录问题: 2.在每个组件内定义一条变量scrollWatch默认为true,在绑定滚动监听事件时加个if判断,只有在scrollWatch

vue监听滚动事件实现滚动监听

在vue中实现滚动监听和原生js无太大差异,下面是一个简单的demo,可在控制台查看结果 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript" src="https://unpkg

Bootstrap教程JS插件滚动监听学习笔记分享

本文主要来学习一下JavaScript插件--滚动监听. 1.案例 滚动监听插件可以根据滚动条的位置自动更新所对应的导航标记.你可以试试滚动这个页面,看看左侧导航的变化. 先把实现的代码上了,你可以通过测试代码先来看看效果. <!DOCTYPE html> <html> <head> <title>Bootstrap</title> <meta name="viewport" content="width=de

Bootstrap滚动监听(Scrollspy)插件详解

滚动监听(Scrollspy)插件,即自动更新导航插件,会根据滚动条的位置自动更新对应的导航目标.其基本的实现是随着您的滚动,基于滚动条的位置向导航栏添加 .active class. 如果您想要单独引用该插件的功能,那么您需要引用 scrollspy.js.或者,正如 Bootstrap 插件概览 一章中所提到,您可以引用 bootstrap.js 或压缩版的 bootstrap.min.js. 一.用法 您可以向顶部导航添加滚动监听行为: 1.通过 data 属性:向您想要监听的元素(通常是

Android实现美团、大众点评的购买悬浮效果(ScrollView滚动监听)

随着移动互联网的快速发展,它已经和我们的生活息息相关了,在公交地铁里面都能看到很多人的人低头看着自己的手机屏幕,从此"低头族"一词就产生了,作为一名移动行业的开发人员,我自己也是一名"低头族",上下班时间在公交地铁上看看新闻来打发下时间,有时候也会看看那些受欢迎的App的一些界面效果,为什么人家的app那么受欢迎?跟用户体验跟UI设计也有直接的关系,最近在美团和大众点评的App看到如下效果,我感觉用户好,很人性化,所以自己也尝试着实现了下,接下来就讲解下实现思路!