直接上代码啦
import 'package:flutter/material.dart'; class StickyDemo extends StatefulWidget { @override _StickyDemoState createState() => _StickyDemoState(); } class _StickyDemoState extends State<StickyDemo> with SingleTickerProviderStateMixin { TabController tabController; @override void initState() { super.initState(); this.tabController = TabController(length: 2, vsync: this); } @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: <Widget>[ SliverAppBar( pinned: true, elevation: 0, expandedHeight: 250, flexibleSpace: FlexibleSpaceBar( title: Text('Sliver-sticky效果'), background: Image.network( 'http://img1.mukewang.com/5c18cf540001ac8206000338.jpg', fit: BoxFit.cover, ), ), ), SliverPersistentHeader( pinned: true, delegate: StickyTabBarDelegate( child: TabBar( labelColor: Colors.black, controller: this.tabController, tabs: <Widget>[ Tab(text: 'Home'), Tab(text: 'Profile'), ], ), ), ), SliverFillRemaining( child: TabBarView( controller: this.tabController, children: <Widget>[ Center(child: Text('Content of Home')), Center(child: Text('Content of Profile')), ], ), ), ], ), ); } } class StickyTabBarDelegate extends SliverPersistentHeaderDelegate { final TabBar child; StickyTabBarDelegate({@required 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; } }
往下滑动效果图:
最后tab就吸附固定在顶部了;再往上滑动,顶部的图片就会出现了;
更详细的请看原博客 https://segmentfault.com/a/1190000019902201
这是一种实现方式,当然还有其他方式,他们三也可以实现NestedScrollViewRefreshIndicator、NestedScrollView和SliverPersistentHeader,以下代码是项目的代码,使用结构简单写下,其中有用到Bloc模式,但是和实现效果无关哈
NestedScrollViewRefreshIndicator( onRefresh: onRefresh, child: NestedScrollView( headerSliverBuilder: (c, f) { return buildSliverHeader(_appBarHeight, applicationBloc); }, body: Column( children: <Widget>[ primaryTabBar, Expanded( child: TabBarView( controller: this.tabController, children: <Widget>[ Center(child: Text('Content of Home')), Center(child: Text('Content of Profile')), ], ), ), ], ), ), ), var primaryTabBar = Container( height: 36, child: TabBar( labelColor: Colors.black, controller: this.tabController, tabs: <Widget>[ Tab(text: 'Home'), Tab(text: 'Profile'), ], ), ); List<Widget> buildSliverHeader(appBarHeight, applicationBloc) { var widgets = <Widget>[]; widgets.add( SliverPersistentHeader( pinned: false, delegate: _SliverAppBarDelegate( Column(), appBarHeight), ), ); return widgets; }