vlambda博客
学习文章列表

【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), SizedBox(height: 10,), _buildSalesDataWidget(state), ]), ) ], )
class SliverHeaderDelegate extends SliverPersistentHeaderDelegate { SliverHeaderDelegate({ @required this.minHeight, @required this.maxHeight, @required this.onBind, });
final double minHeight; final double maxHeight; final BuildCallback onBind; Widget _child;
@override double get minExtent => minHeight;
@override double get maxExtent => max(maxHeight, minHeight);
@override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { _child = onBind(context, shrinkOffset, overlapsContent); return SizedBox.expand(child: _child); }
@override bool shouldRebuild(SliverHeaderDelegate oldDelegate) { return maxHeight != oldDelegate.maxHeight || minHeight != oldDelegate.minHeight || _child != oldDelegate._child; }}
typedef BuildCallback = Widget Function(BuildContext context, double shrinkOffset, bool overlapsContent);