美文网首页Flutter烂笔头Flutter
Flutter吸附效果如何实现?

Flutter吸附效果如何实现?

作者: RidingWind2023 | 来源:发表于2019-06-14 00:05 被阅读136次

    本文多图预警,请注意在wifi下观看O(∩_∩)O~~
    很多软件都有吸附顶部的效果,一图胜千言(这里偷懒,使用的是简书中的图)。

    吸附效果
    而在android中一般是使用 AppBarLayout + CoordinatorLayout + CollapsingToolbarLayout来实现的,那么在flutter中,
    这个效果该如何实现呢?
    这里我们先看一个概念,叫 CustomScrollView。

    CustomScrollView

    官方文档是这样解释的。一个使用slivers来创建自定义滚动效果的ScrollView
    CustomScrollView让你直接提供 slivers来创建不同的滚动效果,比如lists,grids 以及 expanding headers。
    如果要创建一个包含 可伸展的appbar ,后面跟着list 和grid 这样的滚动视图,可以使用这三种slivers:SliverAppBarSliverAppBar
    SliverGrid
    在这些slivers中的widget必须产生 RenderSliver对象。
    为了控制这些滚动视图的初始滚动偏移量,可以通过 controller和他的 ScrollController.initialScrollOffset属性来设置。

    下面的例子展示了 scroll view包含 flexible pinned app bar, 一个grid 和一个无限的list。

    class CustomWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return CustomScrollView(
          slivers: <Widget>[
            SliverAppBar(
                pinned: true,
                expandedHeight: 150.0,
                flexibleSpace: const FlexibleSpaceBar(
                  title: Text('Available seats'),
                ),
                actions: <Widget>[
                  IconButton(
                    icon: const Icon(Icons.add_circle),
                    tooltip: 'Add new entry',
                    onPressed: () {
                      /* ... */
                    },
                  ),
                ]),
            SliverGrid(
              gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                maxCrossAxisExtent: 200.0,
                mainAxisSpacing: 10.0,
                crossAxisSpacing: 10.0,
                childAspectRatio: 4.0,
              ),
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    alignment: Alignment.center,
                    color: Colors.teal[100 * (index % 9)],
                    child: Text('grid item $index'),
                  );
                },
                childCount: 20,
              ),
            ),
            SliverFixedExtentList(
              itemExtent: 50.0,
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    alignment: Alignment.center,
                    color: Colors.lightBlue[100 * (index % 9)],
                    child: Text('list item $index'),
                  );
                },
              ),
            ),
          ],
        );
      }
    }
    

    效果图见下方SliverAppBar的图,两个合在一起展示了。

    SliverAppBar

    定义: 配套 CustomScrollView使用的material design app bar。
    一个app bar由 一个 toolbar 和 其他潜在的widgets组成,比如 TabBarFlexibleSpaceBar。 App bars 通常会
    通过IconButtons来暴露一个或者多个common actions,后面也可选的跟PopupMenuButton,可以做一些常用操作。
    Sliver app bars 通常被用作 CustomScrollView的第一个孩子,可以根据scroll view中其他孩子的滚动偏移量来动态调整高度。
    如果要使用一个固定高度的app bar 可以看AppBar, 用在Scaffold.appBar这一块。
    这个AppBar展示一些toolbar widgets,leading(最左侧的按钮)、title以及actions,都在bottom之上。如果flexibleSpace
    widget也被指定内容了,它将会被放在 toolbar 和 bottom widget 之下。
    下面这段代码可以被CustomScrollView的[CustomScrollView.slivers]使用:

     SliverAppBar(
       expandedHeight: 150.0,
       flexibleSpace: const FlexibleSpaceBar(
         title: Text('Available seats'),
       ),
       actions: <Widget>[
         IconButton(
           icon: const Icon(Icons.add_circle),
           tooltip: 'Add new entry',
           onPressed: () { /* ... */ },
         ),
       ]
     )
    

    将这段代码放入到上面CustomScrollView的样例代码中,效果如下:

    SliverAppBar

    下面的内容主要是细致分析 SliverAppBar构造函数中 floatingsnappinned取不同的值对于交互效果的影响变化。

    动画样例

    App bar -- [floating]: false, [pinned]: false, [snap]: false:

    app_bar
    现象描述:
    • 向上滑动时: AppBar 延伸区域先收起来->appbar滑出去->list滑动出去
    • 向下滑动时: list滑动回来->appbar滑回来->延伸区域滑回来

    App bar -- [floating]: true, [pinned]: false, [snap]: false:

    app_bar_floating
    现象描述:
    • 向上滑动时: AppBar 延伸区域先收起来->appbar滑出去->list滑动出去
    • 向下滑动时: appbar滑回来->延伸区域滑回来->list滑回来

    App bar -- [floating]: true, [pinned]: false, [snap]: true:

    app_bar_floating_snap
    现象描述:
    • 向上滑动时: AppBar 延伸区域先收起来->appbar滑出去->list滑动出去
    • 向下滑动时: appbar滑回来->延伸区域在检测到有轻微下滑的加速度就会动画形式直接展开盖在list之上->list滑回来

    App bar -- [floating]: true, [pinned]: true, [snap]: false:

    app_bar_pinned_floating
    现象描述:
    • 向上滑动时: AppBar 延伸区域先收起来->list滑动出去
    • 向下滑动时: 延伸区域滑回来->list滑回来

    App bar -- [floating]: true, [pinned]: true, [snap]: true:

    app_bar_pinned_floating_snap
    现象描述:
    • 向上滑动时: AppBar 延伸区域先收起来->list滑动出去
    • 向下滑动时: 延伸区域在检测到有轻微下滑的加速度就会动画形式直接展开盖在list之上->list滑回来

    App bar with [floating]: false, [pinned]: true, [snap]: false:

    app_bar_pinned
    现象描述:
    • 向上滑动时: AppBar 延伸区域先收起来->list滑动出去
    • 向下滑动时: list滑回来->延伸区域滑回来

    snap属性只能在float属性为true的情况下设置.
    总结下来
    pinned最容易理解,是否固定appbar不滑出屏幕。
    floating改变了下滑时候出现优先级的顺序,appbar(以及延伸区域)出现的优先级>list的优先级。
    snap要结合floating,检测到下滑的轻微加速度就会以动画形式将appbar完全展开盖在list之上。
    这里留意到一个现象是在慢速持续的向下滑动时,snap的值true和false差别不大。
    本文样例分支代码已上传github ,分支CustomScrollView分支。


    如果你觉得这篇文章对你有益,还请帮忙转发和点赞,万分感谢。

    Flutter烂笔头
    您的关注将是我坚持的动力源泉,再次感谢。

    相关文章

      网友评论

        本文标题:Flutter吸附效果如何实现?

        本文链接:https://www.haomeiwen.com/subject/wkjyfctx.html