本文多圖預警,請注意在wifi下觀看O(∩_∩)O~~
很多軟體都有吸附頂部的效果,一圖勝千言(這裡偷懶,使用的是簡書中的圖)。
這裡我們先看一個概念,叫 CustomScrollView。
CustomScrollView
官方文件是這樣解釋的。一個使用slivers
來建立自定義滾動效果的ScrollView
。
CustomScrollView
讓你直接提供 slivers
來建立不同的滾動效果,比如lists,grids 以及 expanding headers。
如果要建立一個包含 可伸展的appbar ,後面跟著list 和grid 這樣的滾動檢視,可以使用這三種slivers:SliverAppBar
,SliverAppBar
和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組成,比如 TabBar
和 FlexibleSpaceBar
。 App bars 通常會
通過IconButton
s來暴露一個或者多個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
建構函式中 floating
、snap
、pinned
取不同的值對於互動效果的影響變化。
動畫樣例
App bar -- [floating]: false, [pinned]: false, [snap]: false:
現象描述:
- 向上滑動時: AppBar 延伸區域先收起來->appbar滑出去->list滑動出去
- 向下滑動時: list滑動回來->appbar滑回來->延伸區域滑回來
App bar -- [floating]: true, [pinned]: false, [snap]: false:
現象描述:
- 向上滑動時: AppBar 延伸區域先收起來->appbar滑出去->list滑動出去
- 向下滑動時: appbar滑回來->延伸區域滑回來->list滑回來
App bar -- [floating]: true, [pinned]: false, [snap]: true:
現象描述:
- 向上滑動時: AppBar 延伸區域先收起來->appbar滑出去->list滑動出去
- 向下滑動時: appbar滑回來->延伸區域在檢測到有輕微下滑的加速度就會動畫形式直接展開蓋在list之上->list滑回來
App bar -- [floating]: true, [pinned]: true, [snap]: false:
現象描述:
- 向上滑動時: AppBar 延伸區域先收起來->list滑動出去
- 向下滑動時: 延伸區域滑回來->list滑回來
App bar -- [floating]: true, [pinned]: true, [snap]: true:
現象描述:
- 向上滑動時: AppBar 延伸區域先收起來->list滑動出去
- 向下滑動時: 延伸區域在檢測到有輕微下滑的加速度就會動畫形式直接展開蓋在list之上->list滑回來
App bar with [floating]: false, [pinned]: true, [snap]: false:
現象描述:
- 向上滑動時: AppBar 延伸區域先收起來->list滑動出去
- 向下滑動時: list滑回來->延伸區域滑回來
snap
屬性只能在float
屬性為true的情況下設定.
總結下來
pinned
最容易理解,是否固定appbar不滑出螢幕。
floating
改變了下滑時候appbar出現優先順序的順序,appbar(以及延伸區域)出現的優先順序>list的優先順序。
snap
要結合floating
,檢測到下滑的輕微加速度就會以動畫形式將appbar完全展開蓋在list之上。
這裡留意到一個現象是在慢速持續的向下滑動時,snap
的值true和false差別不大。
本文樣例分支程式碼已上傳github ,分支CustomScrollView分支。
如果你覺得這篇文章對你有益,還請幫忙轉發和點贊,萬分感謝。
您的關注將是我堅持的動力源泉,再次感謝。