前言
在業務開發中我們經常會有滾動吸頂的效果,目前Flutter也有很多種實現方式,這裡介紹一下本人在開發中使用到的基於NestedScrollView實現的滾動吸頂元件;以及中間涉及的各種定位的佈局操作;
效果
NestedScrollView
首先了解一下NestedScrollView滾動元件;
NestedScrollView:支援巢狀滑動的ScrollView;
屬性
屬性 | 說明 | 預設值 |
---|---|---|
controller | 滾動監聽 | 無 |
scrollDirection | 滾動方向 | Axis.vertical 預設垂直方向 |
reverse | 是都倒敘 | false 預設值 |
physics | 控制使用者滾動檢視的互動 | AlwaysScrollableScrollPhysics 總是可以滑動 NeverScrollableScrollPhysics 禁止滾動 BouncingScrollPhysics 內容超過一屏上拉有回彈效果 ClampingScrollPhysics 包裹內容不會有回彈 |
headerSliverBuilder | 摺疊頭部 | 無 |
body | 滾動元件實體 | 無 |
NestedScrollView摺疊部分使用SliverAppBar來實現
SliverAppBar
程式碼示例
NestedScrollView(
controller: _scrollController,
headerSliverBuilder: _headerSliverBuilder,
body: buildSliverBody(context)
)
///頁面滾動頭部處理
List<Widget> _headerSliverBuilder(BuildContext context, bool innerBoxIsScrolled) {
return <Widget> [
buildSliverAppBar(context)
];
}
///導航部分渲染
Widget buildSliverAppBar(BuildContext context) {
return SliverAppBar(
//當此值為true時 SliverAppBar 會固定在頁面頂部
//當此值為fase時 SliverAppBar 會隨著滑動向上滑動
pinned: true,
//滾動是是否拉伸圖片
stretch: true,
//展開區域的高度
expandedHeight: 500,
//當snap配置為true時,向下滑動頁面,SliverAppBar(以及其中配置的flexibleSpace內容)會立即顯示出來,
//反之當snap配置為false時,向下滑動時,只有當ListView的資料滑動到頂部時,SliverAppBar才會下拉顯示出來。
snap: false,
//陰影
elevation: 0,
//背景顏色
backgroundColor: headerWhite? Colors.white : Color(0xFFF4F5F7),
//App bar 的亮度,有白色和黑色兩種主題,預設值為 ThemeData.primaryColorBrightness
brightness: Brightness.light,
//在標題左側顯示的一個控制元件,在首頁通常顯示應用的 logo;在其他介面通常顯示為返回按鈕
leading: IconButton(
icon: Image.network(backIcon, height: 22, width: 22,),
onPressed: (){
//TODO: 返回事件處理
}
),
//一個顯示在 AppBar 下方的控制元件,高度和 AppBar 高度一樣, // 可以實現一些特殊的效果,該屬性通常在 SliverAppBar 中使用
flexibleSpace: FlexibleSpaceBar(
title: headerWhite ? Text('長津湖', style: TextStyle(
color: Color(0xFF333333),
fontWeight: FontWeight.w700,
fontSize: 17,
fontFamily: 'PingFangSC-Semibold'
),) : Text(''),
//標題居中
centerTitle: true,
background: buildAppBarBackground(context),
),
);
}
屬性
const SliverAppBar({
Key key,
this.leading, //在標題左側顯示的一個控制元件,在首頁通常顯示應用的 logo;在其他介面通常顯示為返回按鈕
this.automaticallyImplyLeading = true,//? 控制是否應該嘗試暗示前導小部件為null
this.title, //當前介面的標題文字
this.actions, //一個 Widget 列表,代表 Toolbar 中所顯示的選單,對於常用的選單,通常使用 IconButton 來表示;對於不常用的選單通常使用 PopupMenuButton 來顯示為三個點,點選後彈出二級選單
this.flexibleSpace, //一個顯示在 AppBar 下方的控制元件,高度和 AppBar 高度一樣, // 可以實現一些特殊的效果,該屬性通常在 SliverAppBar 中使用
this.bottom, //一個 AppBarBottomWidget 物件,通常是 TabBar。用來在 Toolbar 標題下面顯示一個 Tab 導航欄
this.elevation, //陰影
this.forceElevated = false,
this.backgroundColor, //APP bar 的顏色,預設值為 ThemeData.primaryColor。改值通常和下面的三個屬性一起使用
this.brightness, //App bar 的亮度,有白色和黑色兩種主題,預設值為 ThemeData.primaryColorBrightness
this.iconTheme, //App bar 上圖示的顏色、透明度、和尺寸資訊。預設值為 ThemeData().primaryIconTheme
this.textTheme, //App bar 上的文字主題。預設值為 ThemeData().primaryTextTheme
this.primary = true, //此應用欄是否顯示在螢幕頂部
this.centerTitle, //標題是否居中顯示,預設值根據不同的作業系統,顯示方式不一樣,true居中 false居左
this.titleSpacing = NavigationToolbar.kMiddleSpacing,//橫軸上標題內容 周圍的間距
this.expandedHeight, //展開高度
this.floating = false, //是否隨著滑動隱藏標題
this.pinned = false, //是否固定在頂部
this.snap = false, //與floating結合使用
})
flexibleSpace
flexibleSpace: FlexibleSpaceBar(
//是否展示標題
title: headerWhite ? Text('長津湖', style: TextStyle(
color: Color(0xFF333333),
fontWeight: FontWeight.w700,
fontSize: 17,
fontFamily: 'PingFangSC-Semibold'
),) : Text(''),
//標題居中
centerTitle: true,
//摺疊部分背景圖片
background: Container(
height: 400,
width: ScreenUtil().screenWidth,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://p0.meituan.net/movie/0e81560dc9910a6a658a82ec7a054ceb5075992.jpg@464w_644h_1e_1c'),
fit: BoxFit.fill
)
),
),
)
展示標題如下:
不展示標題滾動到某個位置時在展示 如下: