Browse Source

slide menu

master
daivph 5 years ago
parent
commit
05fb012c8c
5 changed files with 567 additions and 12 deletions
  1. +2
    -1
      lib/app.dart
  2. +1
    -11
      lib/presentation/screens/home/view/home_page.dart
  3. +220
    -0
      lib/presentation/screens/slide_menu/drawer_user_controller.dart
  4. +276
    -0
      lib/presentation/screens/slide_menu/home_drawer.dart
  5. +68
    -0
      lib/presentation/screens/slide_menu/navigation_home_screen.dart

+ 2
- 1
lib/app.dart View File

@@ -1,5 +1,6 @@
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/slide_menu/navigation_home_screen.dart';
import 'package:farm_tpf/presentation/screens/splash/view/splash_page.dart';
import 'package:farm_tpf/utils/const_color.dart';
import 'package:flutter/material.dart';
@@ -60,7 +61,7 @@ class _AppViewState extends State<AppView> {
switch (state.status) {
case AuthenticationStatus.authenticated:
_navigator.pushAndRemoveUntil<void>(
HomePage.route(),
NavigationHomeScreen.route(),
(route) => false,
);
break;

+ 1
- 11
lib/presentation/screens/home/view/home_page.dart View File

@@ -15,17 +15,7 @@ class HomePage extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
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."),
],
),
),

+ 220
- 0
lib/presentation/screens/slide_menu/drawer_user_controller.dart View File

@@ -0,0 +1,220 @@
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,
);
}
}
}

+ 276
- 0
lib/presentation/screens/slide_menu/home_drawer.dart View File

@@ -0,0 +1,276 @@
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;
}

+ 68
- 0
lib/presentation/screens/slide_menu/navigation_home_screen.dart View File

@@ -0,0 +1,68 @@
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......
}
}
}
}

Loading…
Cancel
Save