import 'package:flutter/material.dart' hide NestedScrollView;
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@OverRide
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@OverRide
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State
with SingleTickerProviderStateMixin {
TabController tabController;
@OverRide
void initState() {
super.initState();
this.tabController = TabController(length: 4, vsync: this);
}
Future _onRefresh() {}
//tab
Widget _tabListWidget(bool ceiling) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 15),
color: ceiling ? Colors.white : Colors.transparent,
height: 50,
child: TabBar(
labelColor: Colors.black,
controller: this.tabController,
indicatorWeight: 3.5,
indicatorSize: TabBarIndicatorSize.label,
indicatorColor: Colors.red,
labelStyle: TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
unselectedLabelStyle: TextStyle(
fontSize: 15,
),
tabs: [
Tab(text: '精选产品'),
Tab(text: '吃货联盟'),
Tab(text: '电脑办公'),
Tab(text: '生活家电'),
],
),
);
}
//tabview
Widget _tabViewWidget() {
return Container(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Container(
height: 30,
child: Text('$index'),
);
},
itemCount: 100,
),
);
}
@OverRide
Widget build(BuildContext context) {
final double statusBarHeight = MediaQuery.of(context).padding.top;
return Scaffold(
body: NestedScrollViewRefreshIndicator(
onRefresh: _onRefresh,
child: NestedScrollView(
headerSliverBuilder: (context, ceiling) {
return [
//搜索框
SliverAppBar(
pinned: true,
elevation: 0,
title: Text('搜索栏'),
),
//间隔
SliverPadding(
padding: EdgeInsets.all(20),
),
SliverToBoxAdapter(
child: Container(
height: 1500,
color: Colors.red,
),
),
//间隔
SliverPadding(
padding: EdgeInsets.all(20),
),
// tab头部
SliverPersistentHeader(
pinned: true,
delegate: StickyTabBarDelegate(
child: this._tabListWidget(false),
ceiling: this._tabListWidget(true),
),
),
];
},
pinnedHeaderSliverHeightBuilder: () {
return statusBarHeight + kToolbarHeight + 50;
},
innerScrollPositionKeyBuilder: () {
var index = "Tab";
index += tabController.index.toString();
return Key(index);
},
body: TabBarView(
controller: this.tabController,
children: <Widget>[
NestedScrollViewInnerScrollPositionKeyWidget(
Key("Tab0"), _tabViewWidget()),
NestedScrollViewInnerScrollPositionKeyWidget(
Key("Tab1"), _tabViewWidget()),
NestedScrollViewInnerScrollPositionKeyWidget(
Key("Tab2"), _tabViewWidget()),
NestedScrollViewInnerScrollPositionKeyWidget(
Key("Tab3"), _tabViewWidget()),
],
))),
);
}
}
class StickyTabBarDelegate extends SliverPersistentHeaderDelegate {
final child;
final ceiling;
StickyTabBarDelegate({@required this.child, @required this.ceiling});
@OverRide
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return overlapsContent ? this.ceiling : this.child;
}
@OverRide
double get maxExtent => 50;
@OverRide
double get minExtent => 50;
@OverRide
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}