Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class MyBottomNavBar extends StatefulWidget {
- static const int _thresholdItemsNumber = 4;
- static const Color clearColor = Colors.transparent;
- const MyBottomNavBar({
- super.key,
- required this.items,
- required this.onTap, // required this.closeMenu,
- });
- final List<MyNavBarItem> items;
- final Function(int index) onTap;
- @override
- State<MyBottomNavBar> createState() => _MyBottomNavBarState();
- }
- class _MyBottomNavBarState extends State<MyBottomNavBar> {
- PersistentBottomSheetController? _menuController;
- late final bool showAdditionalMenu;
- @override
- void initState() {
- super.initState();
- showAdditionalMenu = widget.items.length > 5;
- }
- @override
- Widget build(BuildContext context) {
- return BlocProvider<NavBarBloc>(
- create: (context) => NavBarBloc(),
- child: Builder(builder: (context) {
- return BlocBuilder<NavBarBloc, NavBarState>(
- builder: (context, navBarState) {
- return navBarState.map(
- itemChanged: (value) {
- return SafeArea(
- bottom: true,
- child: SizedBox(
- height: 90,
- child: Container(
- color: _getBackgroundColor(context),
- padding: _edgeInsets4(),
- child: _getNavBar(
- context,
- value.index,
- ),
- ),
- ),
- );
- },
- );
- },
- );
- }),
- );
- }
- Widget _getNavBar(BuildContext context, int selectedItemIndex) {
- if (showAdditionalMenu) {
- return _buildNavBarWithMenu(context, selectedItemIndex);
- }
- return _buildSimpleNavBar(context, selectedItemIndex);
- }
- Widget _buildSimpleNavBar(BuildContext context, int selectedItemIndex) {
- return Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: widget.items.map(
- (e) {
- return _buildNavBarItem(
- selectedItemIndex,
- e,
- context,
- (int index) {
- context.read<NavBarBloc>().add(NavBarEvent.indexChanged(widget.items.indexOf(e)));
- widget.onTap(widget.items.indexOf(e));
- _closeMenuIfOpened();
- },
- );
- },
- ).toList(),
- );
- }
- Expanded _buildNavBarItem(
- int selectedItemIndex, MyNavBarItem e, BuildContext context, Function(int index) onTap) {
- return Expanded(
- flex: 2,
- child: Container(
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(4.0),
- color: selectedItemIndex == widget.items.indexOf(e)
- ? _getSelectedColor(context)
- : MyBottomNavBar.clearColor,
- ),
- margin: const EdgeInsets.all(4.0),
- child: InkWell(
- enableFeedback: true,
- onTap: () => onTap(widget.items.indexOf(e)),
- child: e,
- ),
- ),
- );
- }
- Widget _buildNavBarWithMenu(BuildContext context, int index) {
- return Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: _buildElementsWithMenu(context, widget.items, index),
- );
- }
- EdgeInsets _edgeInsets4() => const EdgeInsets.all(4.0);
- Widget indexChanged(BuildContext context, int selectedIndex, bool showAdditionalMenu) {
- return SizedBox(
- width: MediaQuery.of(context).size.width,
- );
- }
- List<Widget> _buildElementsWithMenu(BuildContext context, List<MyNavBarItem> items, int selectedIndex) {
- // const padding = EdgeInsets.all(8.0);
- final bool showMoreIcon = items.length > MyBottomNavBar._thresholdItemsNumber;
- final List<Widget> navBar = [];
- for (var element in items) {
- if (items.indexOf(element) < MyBottomNavBar._thresholdItemsNumber) {
- navBar.add(
- _buildNavBarItem(
- selectedIndex,
- element,
- context,
- (int index) {
- context.read<NavBarBloc>().add(NavBarEvent.indexChanged(items.indexOf(element)));
- widget.onTap(items.indexOf(element));
- _closeMenuIfOpened();
- },
- ),
- );
- }
- }
- if (showMoreIcon) {
- final bloc = context.read<NavBarBloc>();
- navBar.add(
- Expanded(
- flex: 2,
- child: Container(
- padding: _edgeInsets4(),
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(4.0),
- color: selectedIndex >= MyBottomNavBar._thresholdItemsNumber
- ? _getSelectedColor(context)
- : MyBottomNavBar.clearColor,
- ),
- child: InkWell(
- enableFeedback: true,
- onTap: () {
- final menuList = items.sublist(4, items.length);
- _showBottomSheet(context, menuList, bloc);
- },
- child: const MyNavBarItem(
- iconData: MyIconData.more,
- label: 'More',
- ),
- ),
- ),
- ),
- );
- }
- return navBar;
- }
- void _closeMenuIfOpened() {
- if (showAdditionalMenu && _menuController != null) {
- _menuController?.close();
- }
- }
- void _showBottomSheet(context, menuList, bloc) {
- _menuController = Scaffold.of(context).showBottomSheet<void>(
- backgroundColor: Colors.white.withOpacity(0.2),
- enableDrag: false,
- shape: const RoundedRectangleBorder(
- borderRadius: BorderRadius.only(topLeft: Radius.circular(0.0), topRight: Radius.circular(0.0)),
- ),
- (BuildContext context) {
- return _buildMenu(menuList, context, bloc);
- },
- elevation: 5.0,
- );
- }
- Widget _buildMenu(menuList, BuildContext context, bloc) {
- return InkWell(
- enableFeedback: true,
- splashColor: Colors.transparent,
- focusColor: Colors.transparent,
- highlightColor: Colors.transparent,
- hoverColor: Colors.transparent,
- overlayColor: MaterialStateProperty.all(Colors.transparent),
- onTap: () {
- _closeMenuIfOpened();
- },
- child: Container(
- color: Colors.white.withOpacity(0.2),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.end,
- children: [
- SizedBox(
- // height: menuList.length * 65.0,
- child: Container(
- decoration: BoxDecoration(
- color: _getBackgroundColor(context),
- borderRadius: const BorderRadius.only(
- topLeft: Radius.circular(20.0),
- topRight: Radius.circular(20.0),
- ),
- ),
- child: ListView.builder(
- itemCount: menuList.length,
- itemBuilder: (context, index) {
- return ListTile(
- leading: MyIcon(menuList[index].iconData),
- title: Text(menuList[index].label ?? ''),
- onTap: () {
- bloc.add(NavBarEvent.indexChanged(MyBottomNavBar._thresholdItemsNumber + index));
- widget.onTap(index + MyBottomNavBar._thresholdItemsNumber);
- _closeMenuIfOpened();
- },
- );
- },
- ),
- ),
- ),
- ],
- ),
- ),
- );
- }
- Color _getBackgroundColor(BuildContext context) {
- if (Theme.of(context).brightness == Brightness.dark) {
- return Theme.of(context).primaryColor;
- } else {
- return Theme.of(context).scaffoldBackgroundColor;
- }
- }
- _getSelectedColor(BuildContext context) {
- if (Theme.of(context).brightness != Brightness.dark) {
- return Theme.of(context).primaryColor.withOpacity(0.2);
- } else {
- return Colors.white.withOpacity(0.2);
- }
- }
- }
- class NavBarBloc extends Bloc<NavBarEvent, NavBarState> {
- int _currentSelectedIndex = 0;
- int get currentIndex => _currentSelectedIndex;
- NavBarBloc()
- : super(
- _ItemChanged(0, DateTime.now()),
- ) {
- on<NavBarEvent>(
- (event, emit) {
- event.map(
- indexChanged: (event) => _indexChanged(event, emit),
- );
- },
- );
- }
- void _indexChanged(_IndexChanged event, Emitter emit) {
- if (_currentSelectedIndex != event.index) {
- _currentSelectedIndex = event.index;
- emit(
- _ItemChanged(
- _currentSelectedIndex,
- DateTime.now(),
- ),
- );
- }
- _currentSelectedIndex = event.index;
- emit(
- _ItemChanged(
- _currentSelectedIndex,
- DateTime.now(),
- ),
- );
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement