【Flutter】导航栏自定义效果
描述:滑动列表时顶部导航栏由高边窄颜色变换
布局:列表顶部是张图片,下面是列表,滚动列表时头部图片移动上去,上面的导航条慢慢出来,导航栏上的图标颜色变换
CustomScrollView(
slivers: <Widget>[
SliverPersistentHeader(
delegate: SliverHeaderDelegate(
minHeight: MediaQuery.of(context).padding.top + 44,
maxHeight: 211,
onBind: (context, shrinkOffset, overlapsContent) {
final minExtent = MediaQuery.of(context).padding.top + 44;
final maxExtent = 211.0;
final toolbarOpacity = 1 - ((maxExtent - shrinkOffset - minExtent) / minExtent).clamp(0.0, 1.0);
final opacity = Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(toolbarOpacity);
final iconColor = ColorTween(begin: Colors.black, end: Colors.white).transform(1 - opacity);
return FlexibleSpaceBar.createSettings(
minExtent: minExtent,
maxExtent: maxExtent,
currentExtent: max(minExtent, maxExtent - shrinkOffset),
toolbarOpacity: toolbarOpacity,
child: GestureDetector(
onTap: (){
print('视频播放界面');
},
child: Stack(
children: <Widget>[
ImageWidget(
width: MediaQuery.of(context).size.width,
height: 211,
imageStr: state.data.coverImage,
),
Positioned.fromRect(
child: Image.asset('assets/ic_play.png'),
rect: Rect.fromLTWH(0, 0, MediaQuery.of(context).size.width, 211),
),
Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(opacity),
boxShadow: [
BoxShadow(
color: Color(0x33999999).withOpacity(opacity.truncate().toDouble()),
blurRadius: 5,
)
],
),
child: SafeArea(
bottom: false,
child: Container(
height: 44,
child: Row(
children: <Widget>[
Expanded(
child: Container(
alignment: Alignment.centerLeft,
child: IconButton(
icon: const Icon(Icons.arrow_back_ios, size: 20),
color: iconColor,
onPressed: () {
Navigator.maybePop(context);
},
),
)),
Expanded(
child: Container(
alignment: Alignment.center,
child: Text(
'直播详情',
style: TextStyle(
fontSize: 18,
color: res.Colors.majorTextColor.withOpacity(opacity),
),
),
)),
Expanded(
child: Container(),
),
],
),
),
),
),
],
),
)
);
},
),
floating: false,
pinned: true,
),
SliverList(
delegate: SliverChildListDelegate([
_buildTimeWidget(state),
_buildliveDataWidget(state),
10,), :
_buildSalesDataWidget(state),
]),
)
],
)
class SliverHeaderDelegate extends SliverPersistentHeaderDelegate {
SliverHeaderDelegate({
this.minHeight,
this.maxHeight,
this.onBind,
});
final double minHeight;
final double maxHeight;
final BuildCallback onBind;
Widget _child;
double get minExtent => minHeight;
double get maxExtent => max(maxHeight, minHeight);
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
_child = onBind(context, shrinkOffset, overlapsContent);
return SizedBox.expand(child: _child);
}
bool shouldRebuild(SliverHeaderDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight || minHeight != oldDelegate.minHeight || _child != oldDelegate._child;
}
}
typedef BuildCallback = Widget Function(BuildContext context, double shrinkOffset, bool overlapsContent);