219 lines
7.1 KiB
Dart
219 lines
7.1 KiB
Dart
import 'package:birzha/constants.dart';
|
|
import 'package:birzha/core/adaptix/adaptix.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:google_nav_bar/google_nav_bar.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
class TabView extends StatefulWidget {
|
|
TabView({required this.items});
|
|
|
|
final List<TabConfigs> items;
|
|
|
|
@override
|
|
_TabViewState createState() => _TabViewState();
|
|
}
|
|
|
|
class _TabViewState extends State<TabView> {
|
|
late final List<GlobalKey<NavigatorState>> navigatorKeys;
|
|
late final PageController controller;
|
|
|
|
Future<bool> pop(BuildContext cntxt) async {
|
|
final tabnavigator = Provider.of<Tabnavigator>(cntxt, listen: false);
|
|
bool canPop = await navigatorKeys[tabnavigator.index].currentState?.maybePop() ?? true;
|
|
if (canPop) {
|
|
return false;
|
|
} else if (tabnavigator.stack.length > 1) {
|
|
setState(() {
|
|
tabnavigator._removefromStack();
|
|
changePage(tabnavigator.stack.last);
|
|
});
|
|
return false;
|
|
} else if (tabnavigator.stack.length == 1 && tabnavigator.index != 0) {
|
|
setState(() {
|
|
tabnavigator._removefromStack();
|
|
changePage(0);
|
|
});
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void changePage(int index) {
|
|
controller.jumpToPage(index);
|
|
}
|
|
|
|
void onPageChange(BuildContext cntxt, int index) {
|
|
Provider.of<Tabnavigator>(cntxt, listen: false)._setIndex(index);
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
navigatorKeys = [for (var item in widget.items) LabeledGlobalKey<NavigatorState>(item.initialRouteName)];
|
|
controller = PageController();
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ChangeNotifierProvider(
|
|
create: (_) => Tabnavigator(
|
|
currentRouteName: (index) {
|
|
return widget.items[index].initialRouteName;
|
|
},
|
|
changePage: changePage,
|
|
pop: pop,
|
|
rootNavContext: context),
|
|
builder: (context, _) => WillPopScope(
|
|
onWillPop: () => pop(context),
|
|
child: Consumer<Tabnavigator>(
|
|
builder: (context, tabnav, __) {
|
|
return Scaffold(
|
|
bottomNavigationBar: Container(
|
|
color: Theme.of(context).bottomNavigationBarTheme.backgroundColor ?? Colors.white,
|
|
padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context) / 2).copyWith(bottom: Adaptix.systemPadding.bottom),
|
|
child: GNav(
|
|
tabBorderRadius: 20.adaptedPx(),
|
|
curve: Curves.easeInCubic,
|
|
duration: Duration(milliseconds: 280),
|
|
selectedIndex: tabnav.index,
|
|
backgroundColor: Colors.transparent,
|
|
gap: 10.adaptedPx(),
|
|
color: Theme.of(context).accentColor,
|
|
activeColor: Theme.of(context).accentColor,
|
|
iconSize: 18.7.adaptedPx(),
|
|
textStyle: Theme.of(context).textTheme.headline2?.copyWith(
|
|
color: Theme.of(context).accentColor,
|
|
fontSize: AppConstants.h2FontSize * 0.93,
|
|
// body text uly headlinedan kichi
|
|
fontWeight: FontWeight.w500,
|
|
height: 1.3),
|
|
tabBackgroundColor: Theme.of(context).bottomNavigationBarTheme.selectedItemColor ?? Colors.grey.shade300,
|
|
tabMargin: EdgeInsets.symmetric(vertical: 8.adaptedPx()),
|
|
padding: EdgeInsets.symmetric(horizontal: 10.adaptedPx(), vertical: 13.2.adaptedPx()),
|
|
onTabChange: (index) {
|
|
onPageChange(context, index);
|
|
changePage(index);
|
|
},
|
|
tabs: <GButton>[
|
|
for (var item in widget.items)
|
|
|
|
/// those items are integrated from each single tabconfig from widget.items
|
|
GButton(
|
|
icon: item.iconData,
|
|
text: item.routeLabel,
|
|
active: true,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
body: Column(
|
|
children: [
|
|
//will create as much Navigators as the length of widget.items.length
|
|
Expanded(
|
|
child: PageView.builder(
|
|
itemCount: widget.items.length,
|
|
onPageChanged: (newPageIndex) {
|
|
onPageChange(context, newPageIndex);
|
|
},
|
|
controller: controller,
|
|
itemBuilder: (_, index) => Navigator(
|
|
initialRoute: widget.items[index].initialRouteName,
|
|
key: navigatorKeys[index],
|
|
onGenerateInitialRoutes: (_, __) {
|
|
return [
|
|
//each first screen of each item in widget.items
|
|
MaterialPageRoute(builder: widget.items[index].firstScreen),
|
|
];
|
|
},
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
///describes each gbutton, each tab and e.t.c -> creaet list of items in [TabView] constructor
|
|
class TabConfigs {
|
|
final int index;
|
|
final Widget Function(BuildContext) firstScreen;
|
|
final String routeLabel;
|
|
final IconData iconData;
|
|
final String initialRouteName;
|
|
|
|
TabConfigs({
|
|
required this.index,
|
|
required this.firstScreen,
|
|
required this.routeLabel,
|
|
required this.iconData,
|
|
required this.initialRouteName,
|
|
});
|
|
}
|
|
|
|
class Tabnavigator extends ChangeNotifier {
|
|
int index = 0;
|
|
Set<int> stack = <int>{0};
|
|
late final Future<bool> Function(BuildContext cntxt) pop;
|
|
late final String Function(int) currentRouteName;
|
|
late final void Function(int) _changePage;
|
|
late final BuildContext rootNavContext;
|
|
|
|
Tabnavigator({required void Function(int) changePage, required this.currentRouteName, required this.pop, required this.rootNavContext}) {
|
|
_changePage = changePage;
|
|
}
|
|
|
|
Map<int, dynamic> _routeSettingsTable = {};
|
|
|
|
void changePage(int page, [dynamic payload]) {
|
|
_routeSettingsTable[page] = payload;
|
|
_changePage(page);
|
|
notifyListeners();
|
|
}
|
|
|
|
dynamic getPayloadOf(int page) {
|
|
return _routeSettingsTable[page];
|
|
}
|
|
|
|
void _setIndex(int i) {
|
|
index = i;
|
|
stack.remove(i);
|
|
stack.add(i);
|
|
notifyListeners();
|
|
}
|
|
|
|
void _removefromStack() {
|
|
_routeSettingsTable.remove(stack.last);
|
|
var listFromStack = [...stack]..removeLast();
|
|
stack = {...listFromStack};
|
|
index = stack.last;
|
|
notifyListeners();
|
|
}
|
|
|
|
static Tabnavigator? maybeOf(BuildContext context) {
|
|
try {
|
|
return Provider.of<Tabnavigator>(context, listen: false);
|
|
} catch (e) {}
|
|
}
|
|
|
|
static backDispatcher(BuildContext context) {
|
|
if (Tabnavigator.maybeOf(context) == null)
|
|
Navigator.of(context).pop();
|
|
else
|
|
Tabnavigator.maybeOf(context)!.pop(context);
|
|
}
|
|
|
|
static String currentRoute(BuildContext context) {
|
|
var nav = Tabnavigator.maybeOf(context);
|
|
if (nav == null) {
|
|
return '/root';
|
|
} else {
|
|
return nav.currentRouteName(nav.index);
|
|
}
|
|
}
|
|
}
|