Last active
March 11, 2021 05:01
-
-
Save VasiliyRusin/08632bce677f82670d5c65fb2b9398f8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
class TestPage extends StatefulWidget { | |
TestPage({Key? key, this.title}) : super(key: key); | |
final String? title; | |
@override | |
_TestPageState createState() => _TestPageState(); | |
} | |
class TabElement { | |
String id; | |
int? count; | |
String? label; | |
TabElement({required this.id, this.count, this.label}) { | |
label ??= id; | |
} | |
} | |
class Element { | |
late String id; | |
} | |
class _TestPageState extends State<TestPage> { | |
final Map<String, List<Element>?> _orders = { | |
'step1': null, | |
'step2': null, | |
'step3': null, | |
'step4': null, | |
'step5': null, | |
'step6': null, | |
'step7': null, | |
'step8': null, | |
'step9': null, | |
'step10': null, | |
'step11': null, | |
'step12': null, | |
'step13': null, | |
'step14': null, | |
}; | |
List<TabElement> get _tabs => _orders.entries | |
.map((el) => TabElement(id: el.key, count: el.value?.length)) | |
.toList(); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: DefaultTabController( | |
length: _tabs.length, | |
child: _nestedScrollView(widget, _tabs, _orders), | |
), | |
); | |
} | |
} | |
Widget _tab(TabElement tab) { | |
return Row( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
if (tab.label != null) | |
Text( | |
tab.label as String, | |
style: TextStyle(color: Colors.black), | |
), | |
], | |
); | |
} | |
Widget _nestedScrollView(TestPage widget, List<TabElement> tabs, orders) { | |
return NestedScrollView( | |
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { | |
return <Widget>[ | |
SliverOverlapAbsorber( | |
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), | |
sliver: _sliverAppBar(context, widget, innerBoxIsScrolled, tabs), | |
), | |
]; | |
}, | |
body: _tabBarView(tabs, orders), | |
); | |
} | |
Widget _sliverAppBar(BuildContext context, TestPage widget, | |
bool innerBoxIsScrolled, List<TabElement> tabs) { | |
return SliverAppBar( | |
title: Text( | |
widget.title as String, | |
style: TextStyle(color: Colors.black), | |
), | |
centerTitle: false, | |
backgroundColor: Colors.white, | |
pinned: true, | |
floating: true, | |
snap: false, | |
forceElevated: innerBoxIsScrolled, | |
bottom: TabBar( | |
isScrollable: true, | |
tabs: | |
tabs.map<Widget>((TabElement tab) => Tab(child: _tab(tab))).toList(), | |
), | |
); | |
} | |
Widget _tabBarView(List<TabElement> tabs, orders) { | |
return TabBarView( | |
children: tabs | |
.map<Widget>((tab) => SafeArea( | |
top: false, | |
bottom: false, | |
child: Builder(builder: (BuildContext context) { | |
return CustomScrollView( | |
key: PageStorageKey<String>(tab.id), | |
slivers: <Widget>[ | |
SliverOverlapInjector( | |
handle: NestedScrollView.sliverOverlapAbsorberHandleFor( | |
context), | |
), | |
SliverFixedExtentList( | |
itemExtent: 48.0, | |
delegate: SliverChildBuilderDelegate( | |
(BuildContext context, int index) { | |
return ListTile( | |
title: Text('Item $index'), | |
); | |
}, | |
childCount: 80, | |
), | |
), | |
], | |
); | |
}))) | |
.toList()); | |
} | |
void main() { | |
runApp(MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
debugShowCheckedModeBanner: false, | |
home: TestPage(title: 'Test'), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment