完整代碼代碼:
import 'package:flutter/material.dart';
class CustomScrollView1 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return CustomScrollView1State();
}
}
class CustomScrollView1State extends State<CustomScrollView1>
with SingleTickerProviderStateMixin {
List<Widget> _tabs = <Widget>[
Tab(
text: "Home",
),
Tab(
text: "Profile",
)
];
List<Widget> _tabViews = <Widget>[
Center(child: Text("Home")),
Center(child: Text("Profile")),
];
TabController _tabController;
@override
void initState() {
super.initState();
this._tabController = TabController(length: _tabs.length, vsync: this);
}
@override
void dispose() {
this._tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverPersistentHeader(
floating: true,
pinned: true,
delegate: SliverCustomHeaderDelegate(
collapsedHeight: 43.0,
expandedHeight: 220.0,
paddingTop: 27.0,
coverImgUrl:
"http://img1.mukewang.com/5c18cf540001ac8206000338.jpg",
title: "練習",
),
),
SliverFillRemaining(
child: TabBarView(
controller: this._tabController,
children: _tabViews,
),
),
],
),
);
}
}
class SliverCustomHeaderDelegate extends SliverPersistentHeaderDelegate {
final double collapsedHeight;
///折疊的高度
final double expandedHeight;
///展開的高度
final double paddingTop;
final String coverImgUrl;
final String title;
SliverCustomHeaderDelegate({
this.collapsedHeight,
this.expandedHeight,
this.paddingTop,
this.coverImgUrl,
this.title,
});
Color makeStickyHeaderBgColor(shrinkOffset) {
final int alpha = (shrinkOffset / (this.maxExtent - this.minExtent) * 255)
.clamp(0, 255)
.toInt();
return Color.fromARGB(alpha, 255, 255, 255);
}
Color makeStickyHeaderTextColor(shrinkOffset, isIcon) {
if (shrinkOffset <= 50) {
return isIcon ? Colors.white : Colors.transparent;
} else {
final int alpha = (shrinkOffset / (this.maxExtent - this.minExtent) * 255)
.clamp(0, 255)
.toInt();
return Color.fromARGB(alpha, 0, 0, 0);
}
}
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
height: this.maxExtent,
width: MediaQuery.of(context).size.width,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
// 背景圖
Container(child: Image.network(this.coverImgUrl, fit: BoxFit.cover)),
// 收起頭部
Positioned(
left: 0,
right: 0,
top: 0,
child: Container(
color: this.makeStickyHeaderBgColor(shrinkOffset), // 背景顏色
child: SafeArea(
bottom: false,
child: Container(
height: this.collapsedHeight,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: this.makeStickyHeaderTextColor(
shrinkOffset, true), // 返回圖標顏色
),
onPressed: () => Navigator.pop(context),
),
Text(
this.title,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: this.makeStickyHeaderTextColor(
shrinkOffset, false), // 標題顏色
),
),
IconButton(
icon: Icon(
Icons.share,
color: this.makeStickyHeaderTextColor(
shrinkOffset, true), // 分享圖標顏色
),
onPressed: () {},
),
],
),
),
),
),
),
],
),
);
}
@override
double get maxExtent => this.expandedHeight;
@override
double get minExtent => this.collapsedHeight + this.paddingTop;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}
效果二:完整代碼:
import 'package:flutter/material.dart';
class CustomScrollView1 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return CustomScrollView1State();
}
}
class CustomScrollView1State extends State<CustomScrollView1>
with SingleTickerProviderStateMixin {
List<Widget> _tabs = <Widget>[
Tab(
text: "Home",
),
Tab(
text: "Profile",
)
];
List<Widget> _tabViews = <Widget>[
Center(child: Text("Home")),
Center(child: Text("Profile")),
];
TabController _tabController;
@override
void initState() {
super.initState();
this._tabController = TabController(length: _tabs.length, vsync: this);
}
@override
void dispose() {
this._tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
floating: true,
snap: true,
pinned: true,
expandedHeight: 250.0,
flexibleSpace: FlexibleSpaceBar(
title: Text("標題"),
background: Image(
image: AssetImage("images/sealand.jpeg"),
fit: BoxFit.cover,
),
),
),
SliverPersistentHeader(
floating: true,
pinned: true,
delegate: StickyTabBarDelegate(
TabBar(
controller: _tabController,
labelColor: Colors.black,
tabs: _tabs,
),
),
),
SliverFillRemaining(
child: TabBarView(
controller: this._tabController,
children: _tabViews,
),
),
],
),
);
}
}
class StickyTabBarDelegate extends SliverPersistentHeaderDelegate {
final TabBar child;
StickyTabBarDelegate(this.child);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return this.child;
}
@override
double get maxExtent => this.child.preferredSize.height;
@override
double get minExtent => this.child.preferredSize.height;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}