From d44608ffa17b088e6f3a600f2f38a2854dc5196f Mon Sep 17 00:00:00 2001 From: Nikhil Vadoliya Date: Sat, 28 Nov 2020 16:18:32 +0530 Subject: [PATCH] implement swipe gesture in left and right drawer --- example/lib/main.dart | 42 +++--- example/lib/main_widget.dart | 5 +- lib/src/slider.dart | 243 +++++++++++++++++++++++++---------- 3 files changed, 199 insertions(+), 91 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index d8dc35b..362a4c1 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -16,7 +16,7 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { GlobalKey _key = - new GlobalKey(); + new GlobalKey(); String title; @override @@ -30,26 +30,26 @@ class _MyAppState extends State { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( - body: SliderMenuContainer( - appBarColor: Colors.white, - key: _key, - appBarPadding: const EdgeInsets.only(top: 20), - sliderMenuOpenSize: 200, - sliderMenuCloseSize: 60, - appBarHeight: 60, - title: Text( - title, - style: TextStyle(fontSize: 22, fontWeight: FontWeight.w700), - ), - sliderMenu: MenuWidget( - onItemClick: (title) { - _key.currentState.closeDrawer(); - setState(() { - this.title = title; - }); - }, - ), - sliderMain: MainWidget()), + body: Padding( + padding: const EdgeInsets.only(top: 0), + child: SliderMenuContainer( + appBarColor: Colors.white, + key: _key, + sliderMenuOpenSize: 200, + title: Text( + title, + style: TextStyle(fontSize: 22, fontWeight: FontWeight.w700), + ), + sliderMenu: MenuWidget( + onItemClick: (title) { + _key.currentState.closeDrawer(); + setState(() { + this.title = title; + }); + }, + ), + sliderMain: MainWidget()), + ), ), ); } diff --git a/example/lib/main_widget.dart b/example/lib/main_widget.dart index 62c4d92..b51c5ff 100644 --- a/example/lib/main_widget.dart +++ b/example/lib/main_widget.dart @@ -27,8 +27,11 @@ class _MainWidgetState extends State { @override Widget build(BuildContext context) { return Container( + margin: const EdgeInsets.all(20), child: ListView.separated( - padding: const EdgeInsets.symmetric(horizontal: 10), + scrollDirection: Axis.vertical, + // physics: BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), itemBuilder: (builder, index) { return LimitedBox( maxHeight: 150, diff --git a/lib/src/slider.dart b/lib/src/slider.dart index 4eddef0..900e51f 100644 --- a/lib/src/slider.dart +++ b/lib/src/slider.dart @@ -11,6 +11,7 @@ class SliderMenuContainer extends StatefulWidget { final int animationDuration; final double sliderMenuOpenSize; final double sliderMenuCloseSize; + final bool isDraggable; final bool hasAppBar; final Color drawerIconColor; @@ -34,6 +35,7 @@ class SliderMenuContainer extends StatefulWidget { Key key, this.sliderMenu, this.sliderMain, + this.isDraggable = true, this.animationDuration = 200, this.sliderMenuOpenSize = 265, this.drawerIconColor = Colors.black, @@ -63,9 +65,17 @@ class SliderMenuContainer extends StatefulWidget { class SliderMenuContainerState extends State with TickerProviderStateMixin { + static const double WIDTH_GESTURE = 50.0; + static const double HEIGHT_GESTURE = 30.0; + static const double BLUR_SHADOW = 20.0; + double slideAmount = 0.0; + double _percent = 0.0; + AnimationController _animationDrawerController; Animation animation; + bool dragging = false; + Widget drawerIcon; /// check whether drawer is open @@ -103,83 +113,94 @@ class SliderMenuContainerState extends State @override Widget build(BuildContext context) { - return Container( - child: Stack(children: [ - /// Display Menu - SlideMenuBar( - slideDirection: widget.slideDirection, - sliderMenu: widget.sliderMenu, - sliderMenuOpenSize: widget.sliderMenuOpenSize, - ), - - /// Displaying the shadow - if (widget.isShadow) ...[ + return LayoutBuilder(builder: (context, constrain) { + return Container( + child: Stack(children: [ + /// Display Menu + SlideMenuBar( + slideDirection: widget.slideDirection, + sliderMenu: widget.sliderMenu, + sliderMenuOpenSize: widget.sliderMenuOpenSize, + ), + + /// Displaying the shadow + if (widget.isShadow) ...[ + AnimatedBuilder( + animation: _animationDrawerController, + builder: (_, child) { + return Transform.translate( + offset: Utils.getOffsetValueForShadow(widget.slideDirection, + animation.value, widget.sliderMenuOpenSize), + child: child, + ); + return child; + }, + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration(shape: BoxShape.rectangle, boxShadow: [ + BoxShadow( + color: widget.shadowColor, + blurRadius: widget.shadowBlurRadius, + // soften the shadow + spreadRadius: widget.shadowSpreadRadius, + //extend the shadow + offset: Offset( + 15.0, // Move to right 15 horizontally + 15.0, // Move to bottom 15 Vertically + ), + ) + ]), + ), + ), + ], + + //Display Main Screen AnimatedBuilder( animation: _animationDrawerController, - builder: (anim, child) { + builder: (_, child) { return Transform.translate( - offset: Utils.getOffsetValueForShadow(widget.slideDirection, - animation.value, widget.sliderMenuOpenSize), + offset: + Utils.getOffsetValues(widget.slideDirection, animation.value), child: child, ); - return child; }, - child: Container( - width: double.infinity, - height: double.infinity, - decoration: BoxDecoration(shape: BoxShape.rectangle, boxShadow: [ - BoxShadow( - color: widget.shadowColor, - blurRadius: widget.shadowBlurRadius, // soften the shadow - spreadRadius: widget.shadowSpreadRadius, //extend the shadow - offset: Offset( - 15.0, // Move to right 15 horizontally - 15.0, // Move to bottom 15 Vertically - ), - ) - ]), - ), - ), - ], - - //Display Main Screen - AnimatedBuilder( - animation: _animationDrawerController, - builder: (anim, child) { - return Transform.translate( - offset: - Utils.getOffsetValues(widget.slideDirection, animation.value), - child: child, - ); - }, - child: Container( - width: double.infinity, - height: double.infinity, - color: widget.appBarColor, - child: Column( - children: [ - if (widget.hasAppBar) - SliderAppBar( - slideDirection: widget.slideDirection, - onTap: () => toggle(), - appBarHeight: widget.appBarHeight, - animationController: _animationDrawerController, - appBarColor: widget.appBarColor, - appBarPadding: widget.appBarPadding, - drawerIcon: widget.drawerIcon, - drawerIconColor: widget.drawerIconColor, - drawerIconSize: widget.drawerIconSize, - isTitleCenter: widget.isTitleCenter, - splashColor: widget.splashColor, - title: widget.title ?? '', - trailing: widget.trailing, - ), - Expanded(child: widget.sliderMain), - ], + child: GestureDetector( + behavior: HitTestBehavior.deferToChild, + onHorizontalDragStart: _onHorizontalDragStart, + onHorizontalDragEnd: _onHorizontalDragEnd, + onHorizontalDragUpdate: (detail) => + _onHorizontalDragUpdate(detail, constrain), + child: Container( + width: double.infinity, + height: double.infinity, + color: widget.appBarColor, + child: Column( + children: [ + if (widget.hasAppBar) + SliderAppBar( + slideDirection: widget.slideDirection, + onTap: () => toggle(), + appBarHeight: widget.appBarHeight, + animationController: _animationDrawerController, + appBarColor: widget.appBarColor, + appBarPadding: widget.appBarPadding, + drawerIcon: widget.drawerIcon, + drawerIconColor: widget.drawerIconColor, + drawerIconSize: widget.drawerIconSize, + isTitleCenter: widget.isTitleCenter, + splashColor: widget.splashColor, + title: widget.title ?? '', + trailing: widget.trailing, + ), + Expanded(child: widget.sliderMain), + ], + ), + ), ), ), - ), - ])); + ])); + }); } @override @@ -187,4 +208,88 @@ class SliderMenuContainerState extends State super.dispose(); _animationDrawerController.dispose(); } + + void _onHorizontalDragStart(DragStartDetails detail) { + if (!widget.isDraggable) return; + + //Check use start dragging from left edge / right edge then enable dragging + if ((widget.slideDirection == SlideDirection.LEFT_TO_RIGHT && + detail.localPosition.dx <= WIDTH_GESTURE) || + (widget.slideDirection == SlideDirection.RIGHT_TO_LEFT && + detail.localPosition.dx >= + WIDTH_GESTURE) /*&& + detail.localPosition.dy <= widget.appBarHeight*/ + ) { + this.setState(() { + dragging = true; + }); + } + //Check use start dragging from top edge / bottom edge then enable dragging + if (widget.slideDirection == SlideDirection.TOP_TO_BOTTOM && + detail.localPosition.dy >= HEIGHT_GESTURE) { + this.setState(() { + dragging = true; + }); + } + } + + void _onHorizontalDragEnd(DragEndDetails detail) { + if (!widget.isDraggable) return; + if (dragging) { + openOrClose(); + setState(() { + dragging = false; + }); + } + } + + void _onHorizontalDragUpdate( + DragUpdateDetails detail, + BoxConstraints constraints, + ) { + if (!widget.isDraggable) return; + // open drawer for left/right type drawer + if (dragging && widget.slideDirection == SlideDirection.LEFT_TO_RIGHT || + widget.slideDirection == SlideDirection.RIGHT_TO_LEFT) { + var globalPosition = detail.globalPosition.dx; + globalPosition = globalPosition < 0 ? 0 : globalPosition; + double position = globalPosition / constraints.maxWidth; + var realPosition = widget.slideDirection == SlideDirection.LEFT_TO_RIGHT + ? position + : (1 - position); + move(realPosition); + } + // open drawer for top/bottom type drawer + /*if (dragging && widget.slideDirection == SlideDirection.TOP_TO_BOTTOM) { + var globalPosition = detail.globalPosition.dx; + globalPosition = globalPosition < 0 ? 0 : globalPosition; + double position = globalPosition / constraints.maxHeight; + var realPosition = widget.slideDirection == SlideDirection.TOP_TO_BOTTOM + ? position + : (1 - position); + move(realPosition); + }*/ + + // close drawer for left/right type drawer + if (isDrawerOpen && + (widget.slideDirection == SlideDirection.LEFT_TO_RIGHT || + widget.slideDirection == SlideDirection.RIGHT_TO_LEFT) && + detail.delta.dx < 15) { + closeDrawer(); + } + } + + move(double percent) { + _percent = percent; + _animationDrawerController.value = percent; + _animationDrawerController.notifyListeners(); + } + + openOrClose() { + if (_percent > 0.3) { + openDrawer(); + } else { + closeDrawer(); + } + } }