Flutter吸附效果如何實現?

本文多圖預警,請注意在wifi下觀看O(∩_∩)O~~
不少軟件都有吸附頂部的效果,一圖勝千言(這裏偷懶,使用的是簡書中的圖)。 android

吸附效果
而在android中通常是使用 AppBarLayout + CoordinatorLayout + CollapsingToolbarLayout來實現的,那麼在flutter中, 這個效果該如何實現呢?
這裏咱們先看一個概念,叫 CustomScrollView。

CustomScrollView

官方文檔是這樣解釋的。一個使用slivers來建立自定義滾動效果的ScrollView
CustomScrollView讓你直接提供 slivers來建立不一樣的滾動效果,好比lists,grids 以及 expanding headers。
若是要建立一個包含 可伸展的appbar ,後面跟着list 和grid 這樣的滾動視圖,可使用這三種slivers:SliverAppBarSliverAppBarSliverGrid
在這些slivers中的widget必須產生 RenderSliver對象。
爲了控制這些滾動視圖的初始滾動偏移量,能夠經過 controller和他的 ScrollController.initialScrollOffset屬性來設置。git

下面的例子展現了 scroll view包含 flexible pinned app bar, 一個grid 和一個無限的list。github

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的圖,兩個合在一塊兒展現了。bash

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]使用:app

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的樣例代碼中,效果以下:
less

SliverAppBar

下面的內容主要是細緻分析 SliverAppBar構造函數中 floatingsnappinned取不一樣的值對於交互效果的影響變化。ide

動畫樣例

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

app_bar

現象描述:

  • 向上滑動時: AppBar 延伸區域先收起來->appbar滑出去->list滑動出去
  • 向下滑動時: list滑動回來->appbar滑回來->延伸區域滑回來

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

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出現優先級的順序,appbar(以及延伸區域)出現的優先級>list的優先級。
snap要結合floating,檢測到下滑的輕微加速度就會以動畫形式將appbar徹底展開蓋在list之上。
這裏留意到一個現象是在慢速持續的向下滑動時,snap的值true和false差異不大。
本文樣例分支代碼已上傳github ,分支CustomScrollView分支。


若是你以爲這篇文章對你有益,還請幫忙轉發和點贊,萬分感謝。

Flutter爛筆頭
您的關注將是我堅持的動力源泉,再次感謝。
相關文章
相關標籤/搜索