| import 'package:farm_tpf/presentation/screens/home/view/home_page.dart'; | import 'package:farm_tpf/presentation/screens/home/view/home_page.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/login/view/login_page.dart'; | import 'package:farm_tpf/presentation/screens/login/view/login_page.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/slide_menu/navigation_home_screen.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/splash/view/splash_page.dart'; | import 'package:farm_tpf/presentation/screens/splash/view/splash_page.dart'; | ||||
| import 'package:farm_tpf/utils/const_color.dart'; | import 'package:farm_tpf/utils/const_color.dart'; | ||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| switch (state.status) { | switch (state.status) { | ||||
| case AuthenticationStatus.authenticated: | case AuthenticationStatus.authenticated: | ||||
| _navigator.pushAndRemoveUntil<void>( | _navigator.pushAndRemoveUntil<void>( | ||||
| HomePage.route(), | |||||
| NavigationHomeScreen.route(), | |||||
| (route) => false, | (route) => false, | ||||
| ); | ); | ||||
| break; | break; |
| child: Column( | child: Column( | ||||
| mainAxisSize: MainAxisSize.min, | mainAxisSize: MainAxisSize.min, | ||||
| children: <Widget>[ | children: <Widget>[ | ||||
| Text("logged in." | |||||
| // 'UserID: ${context.bloc<AuthenticationBloc>().state.user.id}', | |||||
| ), | |||||
| RaisedButton( | |||||
| child: const Text('Đăng xuất'), | |||||
| onPressed: () { | |||||
| context | |||||
| .bloc<AuthenticationBloc>() | |||||
| .add(AuthenticationLogoutRequested()); | |||||
| }, | |||||
| ), | |||||
| Text("logged in."), | |||||
| ], | ], | ||||
| ), | ), | ||||
| ), | ), |
| import 'package:farm_tpf/utils/const_color.dart'; | |||||
| import 'package:flutter/material.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<DrawerUserController> | |||||
| with TickerProviderStateMixin { | |||||
| ScrollController scrollController; | |||||
| AnimationController iconAnimationController; | |||||
| AnimationController animationController; | |||||
| double scrolloffset = 0.0; | |||||
| @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 { | |||||
| 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<bool> getInitState() async { | |||||
| scrollController.jumpTo( | |||||
| widget.drawerWidth, | |||||
| ); | |||||
| return true; | |||||
| } | |||||
| @override | |||||
| Widget build(BuildContext context) { | |||||
| return Scaffold( | |||||
| backgroundColor: COLOR_CONST.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: <Widget>[ | |||||
| 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: COLOR_CONST.WHITE, | |||||
| boxShadow: <BoxShadow>[ | |||||
| BoxShadow(color: COLOR_CONST.GRAY1, blurRadius: 24), | |||||
| ], | |||||
| ), | |||||
| child: Stack( | |||||
| children: <Widget>[ | |||||
| //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() { | |||||
| //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, | |||||
| ); | |||||
| } | |||||
| } | |||||
| } |
| import 'package:farm_tpf/authentication/authentication.dart'; | |||||
| import 'package:farm_tpf/utils/const_color.dart'; | |||||
| import 'package:flutter/material.dart'; | |||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||||
| class HomeDrawer extends StatefulWidget { | |||||
| const HomeDrawer( | |||||
| {Key key, | |||||
| this.screenIndex, | |||||
| this.iconAnimationController, | |||||
| this.callBackIndex}) | |||||
| : super(key: key); | |||||
| final AnimationController iconAnimationController; | |||||
| final DrawerIndex screenIndex; | |||||
| final Function(DrawerIndex) callBackIndex; | |||||
| @override | |||||
| _HomeDrawerState createState() => _HomeDrawerState(); | |||||
| } | |||||
| class _HomeDrawerState extends State<HomeDrawer> { | |||||
| List<DrawerList> drawerList; | |||||
| @override | |||||
| void initState() { | |||||
| setdDrawerListArray(); | |||||
| super.initState(); | |||||
| } | |||||
| void setdDrawerListArray() { | |||||
| drawerList = <DrawerList>[ | |||||
| DrawerList( | |||||
| index: DrawerIndex.Home, | |||||
| labelName: 'Trang chủ', | |||||
| icon: Icon(Icons.home), | |||||
| ), | |||||
| DrawerList( | |||||
| index: DrawerIndex.Setting, | |||||
| labelName: 'Cài đặt', | |||||
| icon: Icon(Icons.settings), | |||||
| ) | |||||
| ]; | |||||
| } | |||||
| @override | |||||
| Widget build(BuildContext context) { | |||||
| return Container( | |||||
| child: Column( | |||||
| crossAxisAlignment: CrossAxisAlignment.stretch, | |||||
| mainAxisAlignment: MainAxisAlignment.start, | |||||
| children: <Widget>[ | |||||
| Container( | |||||
| width: double.infinity, | |||||
| padding: const EdgeInsets.only(top: 45.0), | |||||
| child: Container( | |||||
| padding: const EdgeInsets.all(16.0), | |||||
| child: Column( | |||||
| crossAxisAlignment: CrossAxisAlignment.start, | |||||
| mainAxisAlignment: MainAxisAlignment.start, | |||||
| children: <Widget>[ | |||||
| AnimatedBuilder( | |||||
| animation: widget.iconAnimationController, | |||||
| builder: (BuildContext context, Widget child) { | |||||
| return ScaleTransition( | |||||
| scale: AlwaysStoppedAnimation<double>( | |||||
| 1.0 - (widget.iconAnimationController.value) * 0.2), | |||||
| child: RotationTransition( | |||||
| turns: AlwaysStoppedAnimation<double>(Tween<double>( | |||||
| begin: 0.0, end: 24.0) | |||||
| .animate(CurvedAnimation( | |||||
| parent: widget.iconAnimationController, | |||||
| curve: Curves.fastOutSlowIn)) | |||||
| .value / | |||||
| 360), | |||||
| child: Container( | |||||
| height: 100, | |||||
| width: 100, | |||||
| decoration: BoxDecoration( | |||||
| borderRadius: BorderRadius.circular(120), | |||||
| border: Border.all( | |||||
| width: 0.35, color: COLOR_CONST.DEFAULT), | |||||
| ), | |||||
| child: ClipRRect( | |||||
| borderRadius: | |||||
| const BorderRadius.all(Radius.circular(10.0)), | |||||
| child: FlutterLogo( | |||||
| size: 10, | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| }, | |||||
| ), | |||||
| Padding( | |||||
| padding: const EdgeInsets.only(top: 8, left: 20), | |||||
| child: Text( | |||||
| 'Võ Phước Đại', | |||||
| style: TextStyle( | |||||
| fontWeight: FontWeight.w600, | |||||
| color: COLOR_CONST.GRAY1, | |||||
| fontSize: 18, | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ], | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| const SizedBox( | |||||
| height: 4, | |||||
| ), | |||||
| Divider( | |||||
| height: 1, | |||||
| color: COLOR_CONST.GRAY1, | |||||
| ), | |||||
| Expanded( | |||||
| child: ListView.builder( | |||||
| physics: const BouncingScrollPhysics(), | |||||
| padding: const EdgeInsets.all(0.0), | |||||
| itemCount: drawerList.length, | |||||
| itemBuilder: (BuildContext context, int index) { | |||||
| return inkwell(drawerList[index]); | |||||
| }, | |||||
| ), | |||||
| ), | |||||
| Divider( | |||||
| height: 1, | |||||
| color: COLOR_CONST.GRAY1, | |||||
| ), | |||||
| Column( | |||||
| children: <Widget>[ | |||||
| ListTile( | |||||
| title: Text( | |||||
| 'Đăng xuất', | |||||
| style: TextStyle( | |||||
| fontWeight: FontWeight.w600, | |||||
| fontSize: 16, | |||||
| ), | |||||
| textAlign: TextAlign.left, | |||||
| ), | |||||
| trailing: Icon( | |||||
| Icons.power_settings_new, | |||||
| color: Colors.red, | |||||
| ), | |||||
| onTap: () { | |||||
| _clickSignOut(); | |||||
| }, | |||||
| ), | |||||
| SizedBox( | |||||
| height: MediaQuery.of(context).padding.bottom, | |||||
| ) | |||||
| ], | |||||
| ), | |||||
| ], | |||||
| ), | |||||
| ); | |||||
| } | |||||
| Widget inkwell(DrawerList listData) { | |||||
| return Material( | |||||
| color: Colors.white, | |||||
| child: InkWell( | |||||
| splashColor: Colors.grey.withOpacity(0.1), | |||||
| highlightColor: Colors.transparent, | |||||
| onTap: () { | |||||
| navigationtoScreen(listData.index); | |||||
| }, | |||||
| child: Stack( | |||||
| children: <Widget>[ | |||||
| Container( | |||||
| padding: const EdgeInsets.only(top: 8.0, bottom: 8.0), | |||||
| child: Row( | |||||
| children: <Widget>[ | |||||
| Container( | |||||
| width: 6.0, | |||||
| height: 46.0, | |||||
| ), | |||||
| const Padding( | |||||
| padding: EdgeInsets.all(4.0), | |||||
| ), | |||||
| listData.isAssetsImage | |||||
| ? Container( | |||||
| width: 24, | |||||
| height: 24, | |||||
| child: Image.asset(listData.imageName, | |||||
| color: widget.screenIndex == listData.index | |||||
| ? COLOR_CONST.DEFAULT | |||||
| : COLOR_CONST.BLACK), | |||||
| ) | |||||
| : Icon(listData.icon.icon, | |||||
| color: widget.screenIndex == listData.index | |||||
| ? COLOR_CONST.DEFAULT | |||||
| : COLOR_CONST.BLACK), | |||||
| const Padding( | |||||
| padding: EdgeInsets.all(4.0), | |||||
| ), | |||||
| Text( | |||||
| listData.labelName, | |||||
| style: TextStyle( | |||||
| fontWeight: FontWeight.w500, | |||||
| fontSize: 16, | |||||
| color: widget.screenIndex == listData.index | |||||
| ? COLOR_CONST.DEFAULT | |||||
| : COLOR_CONST.BLACK, | |||||
| ), | |||||
| textAlign: TextAlign.left, | |||||
| ), | |||||
| ], | |||||
| ), | |||||
| ), | |||||
| widget.screenIndex == listData.index | |||||
| ? AnimatedBuilder( | |||||
| animation: widget.iconAnimationController, | |||||
| builder: (BuildContext context, Widget child) { | |||||
| return Transform( | |||||
| transform: Matrix4.translationValues( | |||||
| (MediaQuery.of(context).size.width * 0.75 - 64) * | |||||
| (1.0 - | |||||
| widget.iconAnimationController.value - | |||||
| 1.0), | |||||
| 0.0, | |||||
| 0.0), | |||||
| child: Padding( | |||||
| padding: EdgeInsets.only(top: 8, bottom: 8), | |||||
| child: Container( | |||||
| width: | |||||
| MediaQuery.of(context).size.width * 0.75 - 64, | |||||
| height: 46, | |||||
| decoration: BoxDecoration( | |||||
| color: COLOR_CONST.DEFAULT.withOpacity(0.2), | |||||
| borderRadius: new BorderRadius.only( | |||||
| topLeft: Radius.circular(0), | |||||
| topRight: Radius.circular(28), | |||||
| bottomLeft: Radius.circular(0), | |||||
| bottomRight: Radius.circular(28), | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| }, | |||||
| ) | |||||
| : const SizedBox() | |||||
| ], | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| } | |||||
| Future<void> navigationtoScreen(DrawerIndex indexScreen) async { | |||||
| widget.callBackIndex(indexScreen); | |||||
| } | |||||
| _clickSignOut() { | |||||
| context.bloc<AuthenticationBloc>().add(AuthenticationLogoutRequested()); | |||||
| } | |||||
| } | |||||
| enum DrawerIndex { Home, Setting } | |||||
| class DrawerList { | |||||
| DrawerList({ | |||||
| this.isAssetsImage = false, | |||||
| this.labelName = '', | |||||
| this.icon, | |||||
| this.index, | |||||
| this.imageName = '', | |||||
| }); | |||||
| String labelName; | |||||
| Icon icon; | |||||
| bool isAssetsImage; | |||||
| String imageName; | |||||
| DrawerIndex index; | |||||
| } |
| import 'package:farm_tpf/presentation/screens/home/home.dart'; | |||||
| import 'package:farm_tpf/utils/const_color.dart'; | |||||
| import 'package:flutter/material.dart'; | |||||
| import 'drawer_user_controller.dart'; | |||||
| import 'home_drawer.dart'; | |||||
| class NavigationHomeScreen extends StatefulWidget { | |||||
| static Route route() { | |||||
| return MaterialPageRoute<void>(builder: (_) => NavigationHomeScreen()); | |||||
| } | |||||
| @override | |||||
| _NavigationHomeScreenState createState() => _NavigationHomeScreenState(); | |||||
| } | |||||
| class _NavigationHomeScreenState extends State<NavigationHomeScreen> { | |||||
| Widget screenView; | |||||
| DrawerIndex drawerIndex; | |||||
| @override | |||||
| void initState() { | |||||
| drawerIndex = DrawerIndex.Home; | |||||
| screenView = HomePage(); | |||||
| super.initState(); | |||||
| } | |||||
| @override | |||||
| Widget build(BuildContext context) { | |||||
| return Container( | |||||
| color: COLOR_CONST.DEFAULT, | |||||
| child: SafeArea( | |||||
| top: false, | |||||
| bottom: false, | |||||
| child: Scaffold( | |||||
| backgroundColor: COLOR_CONST.WHITE, | |||||
| body: DrawerUserController( | |||||
| screenIndex: drawerIndex, | |||||
| drawerWidth: MediaQuery.of(context).size.width * 0.75, | |||||
| onDrawerCall: (DrawerIndex drawerIndexdata) { | |||||
| changeIndex(drawerIndexdata); | |||||
| //callback from drawer for replace screen as user need with passing DrawerIndex(Enum index) | |||||
| }, | |||||
| screenView: screenView, | |||||
| //we replace screen view as we need on navigate starting screens like MyHomePage, HelpScreen, FeedbackScreen, etc... | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| } | |||||
| void changeIndex(DrawerIndex drawerIndexdata) { | |||||
| if (drawerIndex != drawerIndexdata) { | |||||
| drawerIndex = drawerIndexdata; | |||||
| if (drawerIndex == DrawerIndex.Home) { | |||||
| setState(() { | |||||
| screenView = HomePage(); | |||||
| }); | |||||
| } else if (drawerIndex == DrawerIndex.Setting) { | |||||
| setState(() { | |||||
| screenView = HomePage(); | |||||
| }); | |||||
| } else { | |||||
| //do in your way...... | |||||
| } | |||||
| } | |||||
| } | |||||
| } |