import 'package:farm_tpf/data/repository/user_repository.dart'; import 'package:farm_tpf/presentation/screens/notification/update_count_noti_bloc.dart'; import 'package:farm_tpf/utils/const_color.dart'; import 'package:farm_tpf/utils/pref.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'home_drawer.dart'; class DrawerUserController extends StatefulWidget { const DrawerUserController({ Key key, this.drawerWidth = 250, this.onDrawerCall, this.screenView, this.animatedIconData = AnimatedIcons.arrow_menu, this.menuView, this.drawerIsOpen, this.screenIndex, }) : super(key: key); final double drawerWidth; final Function(DrawerIndex) onDrawerCall; final Widget screenView; final Function(bool) drawerIsOpen; final AnimatedIconData animatedIconData; final Widget menuView; final DrawerIndex screenIndex; @override _DrawerUserControllerState createState() => _DrawerUserControllerState(); } class _DrawerUserControllerState extends State with TickerProviderStateMixin { ScrollController scrollController; AnimationController iconAnimationController; AnimationController animationController; UserRepository _userRepository = UserRepository(); double scrolloffset = 0.0; var pref = LocalPref(); final updateFullName = Get.put(UpdateFullName()); @override void initState() { animationController = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this); iconAnimationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 0)); iconAnimationController ..animateTo(1.0, duration: const Duration(milliseconds: 0), curve: Curves.fastOutSlowIn); scrollController = ScrollController(initialScrollOffset: widget.drawerWidth); scrollController ..addListener(() { if (scrollController.offset <= 0) { if (scrolloffset != 1.0) { setState(() { scrolloffset = 1.0; try { //open Drawer updateCountNotiBloc.getNotifications((data) {}, (err) {}); widget.drawerIsOpen(true); } catch (_) {} }); } iconAnimationController.animateTo(0.0, duration: const Duration(milliseconds: 0), curve: Curves.fastOutSlowIn); } else if (scrollController.offset > 0 && scrollController.offset < widget.drawerWidth) { iconAnimationController.animateTo( (scrollController.offset * 100 / (widget.drawerWidth)) / 100, duration: const Duration(milliseconds: 0), curve: Curves.fastOutSlowIn); } else if (scrollController.offset <= widget.drawerWidth) { if (scrolloffset != 0.0) { setState(() { scrolloffset = 0.0; try { widget.drawerIsOpen(false); } catch (_) {} }); } iconAnimationController.animateTo(1.0, duration: const Duration(milliseconds: 0), curve: Curves.fastOutSlowIn); } }); WidgetsBinding.instance.addPostFrameCallback((_) => getInitState()); super.initState(); } Future getInitState() async { scrollController.jumpTo( widget.drawerWidth, ); return true; } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.WHITE, body: SingleChildScrollView( controller: scrollController, scrollDirection: Axis.horizontal, physics: const PageScrollPhysics(parent: ClampingScrollPhysics()), child: SizedBox( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width + widget.drawerWidth, //we use with as screen width and add drawerWidth (from navigation_home_screen) child: Row( children: [ SizedBox( width: widget.drawerWidth, //we divided first drawer Width with HomeDrawer and second full-screen Width with all home screen, we called screen View height: MediaQuery.of(context).size.height, child: AnimatedBuilder( animation: iconAnimationController, builder: (BuildContext context, Widget child) { return Transform( //transform we use for the stable drawer we, not need to move with scroll view transform: Matrix4.translationValues( scrollController.offset, 0.0, 0.0), child: HomeDrawer( screenIndex: widget.screenIndex == null ? DrawerIndex.Home : widget.screenIndex, iconAnimationController: iconAnimationController, callBackIndex: (DrawerIndex indexType) { onDrawerClick(); try { widget.onDrawerCall(indexType); } catch (e) {} }, ), ); }, ), ), SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, //full-screen Width with widget.screenView child: Container( decoration: BoxDecoration( color: AppColors.WHITE, boxShadow: [ BoxShadow(color: AppColors.GRAY1, blurRadius: 24), ], ), child: Stack( children: [ //this IgnorePointer we use as touch(user Interface) widget.screen View, for example scrolloffset == 1 means drawer is close we just allow touching all widget.screen View IgnorePointer( ignoring: scrolloffset == 1 || false, child: widget.screenView, ), //alternative touch(user Interface) for widget.screen, for example, drawer is close we need to tap on a few home screen area and close the drawer if (scrolloffset == 1.0) InkWell( onTap: () { onDrawerClick(); }, ), // this just menu and arrow icon animation Padding( padding: EdgeInsets.only( top: MediaQuery.of(context).padding.top + 8, left: 8), child: SizedBox( width: AppBar().preferredSize.height - 8, height: AppBar().preferredSize.height - 8, child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular( AppBar().preferredSize.height), child: Center( // if you use your own menu view UI you add form initialization child: widget.menuView != null ? widget.menuView : AnimatedIcon( icon: widget.animatedIconData != null ? widget.animatedIconData : AnimatedIcons.arrow_menu, progress: iconAnimationController), ), onTap: () { FocusScope.of(context) .requestFocus(FocusNode()); onDrawerClick(); }, ), ), ), ), ], ), ), ), ], ), ), ), ); } void onDrawerClick() { getSharedPrefs(); //if scrollcontroller.offset != 0.0 then we set to closed the drawer(with animation to offset zero position) if is not 1 then open the drawer if (scrollController.offset != 0.0) { scrollController.animateTo( 0.0, duration: const Duration(milliseconds: 400), curve: Curves.fastOutSlowIn, ); } else { scrollController.animateTo( widget.drawerWidth, duration: const Duration(milliseconds: 400), curve: Curves.fastOutSlowIn, ); } } Future getSharedPrefs() async { try { updateFullName.init(); var currentFullName = await pref.getString(DATA_CONST.CURRENT_FULL_NAME); if (currentFullName.isEmpty) { var currentUser = await _userRepository.getUser(); pref.saveString(DATA_CONST.CURRENT_FULL_NAME, currentUser.fullName); updateFullName.changeName(currentUser.fullName); } else { updateFullName.changeName(currentFullName); } } catch (e) { print("error: ${e.toString()}"); } } }