轉載請聲明出處!!!
先來簡單看下部分效果圖:
本文內容可能有點多,但是都很簡單,配上效果圖味道更佳~
什麼是SliverAppBar
SliverAppBar 類似於Android中的CollapsingToolbarLayout
,可以輕鬆實現頁面頭部展開、合併的效果。
與AppBar大部分的屬性重合,相當於AppBar的加強版。
先從最基本的效果開始,一步一步做到全效果。
常用屬性
const SliverAppBar({
Key key,
this.leading,//左側的圖標或文字,多爲返回箭頭
this.automaticallyImplyLeading = true,//沒有leading爲true的時候,默認返回箭頭,沒有leading且爲false,則顯示title
this.title,//標題
this.actions,//標題右側的操作
this.flexibleSpace,//可以理解爲SliverAppBar的背景內容區
this.bottom,//SliverAppBar的底部區
this.elevation,//陰影
this.forceElevated = false,//是否顯示陰影
this.backgroundColor,//背景顏色
this.brightness,//狀態欄主題,默認Brightness.dark,可選參數light
this.iconTheme,//SliverAppBar圖標主題
this.actionsIconTheme,//action圖標主題
this.textTheme,//文字主題
this.primary = true,//是否顯示在狀態欄的下面,false就會佔領狀態欄的高度
this.centerTitle,//標題是否居中顯示
this.titleSpacing = NavigationToolbar.kMiddleSpacing,//標題橫向間距
this.expandedHeight,//合併的高度,默認是狀態欄的高度加AppBar的高度
this.floating = false,//滑動時是否懸浮
this.pinned = false,//標題欄是否固定
this.snap = false,//配合floating使用
})
基本效果
return Scaffold(
body: new CustomScrollView(
slivers: <Widget>[
new SliverAppBar(
title: Text("標題"),
expandedHeight: 230.0,
floating: false,
pinned: true,
snap: false,
),
new SliverFixedExtentList(
itemExtent: 50.0,
delegate: new SliverChildBuilderDelegate(
(context, index) => new ListTile(
title: new Text("Item $index"),
),
childCount: 30,
),
),
],
),
);
這是最最最基本的效果了,但是也簡陋的不行,下面開始一步一步改造。
添加leading
leading: new IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
添加actions
actions: <Widget>[
new IconButton(
icon: Icon(Icons.add),
onPressed: () {
print("添加");
},
),
new IconButton(
icon: Icon(Icons.more_horiz),
onPressed: () {
print("更多");
},
),
],
滑動標題上移效果
去掉title,添加flexibleSpace
flexibleSpace: new FlexibleSpaceBar(
title: new Text("標題標題標題"),
centerTitle: true,
collapseMode: CollapseMode.pin,
),
背景圖片沉浸式
項目根目錄下新建images文件夾,存放圖片,隨便選一張即可。
要加載本地圖片,還需要在pubspec.yaml
文件中配置一下
assets:
- images/a.jpg
修改flexibleSpace
flexibleSpace: new FlexibleSpaceBar(
background: Image.asset("images/a.jpg", fit: BoxFit.fill),
),
各種滑動效果演示
-
floating: false, pinned: true, snap: false:
-
floating: true, pinned: true, snap: true:
-
floating: false, pinned: false, snap: false:
-
floating: true, pinned: false, snap: false:
總結:仔細觀察,區別主要在於:
- 標題欄是否跟着一起滑動
- 上滑的時候,SliverAppBar是直接滑上去還是先合併然後再滑上去。
- 下拉的時候,SliverAppBar是直接拉下來還是先拉下來再展開。
添加TabBar
在SliverAppBar的bottom屬性中添加TabBar,直接改造源碼中的例子
var _tabs = <String>[];
_tabs = <String>[
"Tab 1",
"Tab 2",
"Tab 3",
];
/// 加TabBar
DefaultTabController(
length: _tabs.length, // This is the number of tabs.
child: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
// These are the slivers that show up in the "outer" scroll view.
return <Widget>[
SliverOverlapAbsorber(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context),
child: SliverAppBar(
leading: new IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
title: const Text('標題'),
centerTitle: false,
pinned: true,
floating: false,
snap: false,
primary: true,
expandedHeight: 230.0,
elevation: 10,
//是否顯示陰影,直接取值innerBoxIsScrolled,展開不顯示陰影,合併後會顯示
forceElevated: innerBoxIsScrolled,
actions: <Widget>[
new IconButton(
icon: Icon(Icons.more_horiz),
onPressed: () {
print("更多");
},
),
],
flexibleSpace: new FlexibleSpaceBar(
background: Image.asset("images/a.jpg", fit: BoxFit.fill),
),
bottom: TabBar(
tabs: _tabs.map((String name) => Tab(text: name)).toList(),
),
),
),
];
},
body: TabBarView(
// These are the contents of the tab views, below the tabs.
children: _tabs.map((String name) {
//SafeArea 適配劉海屏的一個widget
return SafeArea(
top: false,
bottom: false,
child: Builder(
builder: (BuildContext context) {
return CustomScrollView(
key: PageStorageKey<String>(name),
slivers: <Widget>[
SliverOverlapInjector(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(
context),
),
SliverPadding(
padding: const EdgeInsets.all(10.0),
sliver: SliverFixedExtentList(
itemExtent: 50.0, //item高度或寬度,取決於滑動方向
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ListTile(
title: Text('Item $index'),
);
},
childCount: 30,
),
),
),
],
);
},
),
);
}).toList(),
),
),
),
關於TabBar的使用可以看這篇:https://blog.csdn.net/yechaoa/article/details/90482127
ok,以上的效果基本滿足日常開發需求了,也可以自己改改屬性測試效果。
demo github : https://github.com/yechaoa/flutter_sliverappbar