Line data Source code
1 : import 'package:flutter/material.dart'; 2 : import 'package:liquid_swipe/Helpers/Helpers.dart'; 3 : import 'package:liquid_swipe/Helpers/SlideUpdate.dart'; 4 : import 'package:liquid_swipe/Provider/LiquidProvider.dart'; 5 : import 'package:provider/provider.dart'; 6 : 7 : /// Internal Widget 8 : /// 9 : /// PageDragger is a Widget that handles user gestures and provide the data to the [LiquidProvider] 10 : /// from where we perform animations various other methods. 11 : class PageDragger extends StatefulWidget { 12 : /// Used to make animation faster or slower through it corresponding value 13 : /// default : [FULL_TRANSITION_PX] 14 : final double fullTransitionPX; 15 : 16 : /// Slide Icon whichever provided 17 : final Widget? slideIconWidget; 18 : 19 : /// double value should range from 0.0 - 1.0 20 : final double? iconPosition; 21 : 22 : /// boolean parameter to make user gesture disabled which LiquidSwipe is still Animating 23 : final bool ignoreUserGestureWhileAnimating; 24 : 25 : ///Constructor with some default values 26 1 : PageDragger({ 27 : this.fullTransitionPX = FULL_TRANSITION_PX, 28 : this.slideIconWidget, 29 : this.iconPosition, 30 : this.ignoreUserGestureWhileAnimating = false, 31 : }); 32 : 33 1 : @override 34 1 : _PageDraggerState createState() => _PageDraggerState(); 35 : } 36 : 37 : ///State for PageDragger 38 : class _PageDraggerState extends State<PageDragger> { 39 : GlobalKey _keyIcon = GlobalKey(); 40 : 41 : ///Current [Offset] of the User Touch 42 : Offset? dragStart; 43 : 44 : ///Calculated Slide Direction of the Gesture/Swipe 45 : SlideDirection slideDirection = SlideDirection.none; 46 : 47 : ///Horizontally calculated slide percentage, ranges from 0.0 - 1.0 48 : double slidePercentHor = 0.0; 49 : 50 : ///Same as [slidePercentHor] but for Vertical Swipe and ranges from 0.0 - 1.25 51 : double slidePercentVer = 0.0; 52 : 53 : /// Method invoked when ever user touch the screen and drag starts 54 : /// called at [GestureDetector.onHorizontalDragStart] 55 1 : onDragStart(DragStartDetails details) { 56 2 : final model = Provider.of<LiquidProvider>(context, listen: false); 57 : 58 : ///Ignoring user gesture if the animation is running (optional) 59 1 : if (model.isAnimating && widget.ignoreUserGestureWhileAnimating || 60 1 : model.isUserGestureDisabled) { 61 : return; 62 : } 63 2 : dragStart = details.globalPosition; 64 : } 65 : 66 : ///Updating data while user drags and touch offset changes 67 : ///called at [GestureDetector.onHorizontalDragUpdate] 68 1 : onDragUpdate(DragUpdateDetails details) { 69 1 : if (dragStart != null) { 70 : //Getting new position details 71 1 : final newPosition = details.globalPosition; 72 : //Change in position in x 73 4 : final dx = dragStart!.dx - newPosition.dx; 74 1 : final dy = newPosition.dy; 75 : 76 1 : slideDirection = SlideDirection.none; 77 : //predicting slide direction 78 1 : if (dx > 0.0) { 79 1 : slideDirection = SlideDirection.rightToLeft; 80 1 : } else if (dx < 0.0) { 81 1 : slideDirection = SlideDirection.leftToRight; 82 : } 83 : 84 : //predicting slide percent 85 2 : if (slideDirection != SlideDirection.none) { 86 : //clamp method is used to clamp the value of slidePercent from 0.0 to 1.0, after 1.0 it set to 1.0 87 6 : slidePercentHor = (dx / widget.fullTransitionPX).abs().clamp(0.0, 1.0); 88 1 : slidePercentVer = 89 7 : (dy / MediaQuery.of(context).size.height).abs().clamp(0.0, 1.0); 90 : } 91 : 92 2 : Provider.of<LiquidProvider>(context, listen: false) 93 2 : .updateSlide(SlideUpdate( 94 1 : slideDirection, 95 1 : slidePercentHor, 96 1 : slidePercentVer, 97 : UpdateType.dragging, 98 : )); 99 : } 100 : } 101 : 102 : ///This method executes when user ends dragging and leaves the screen 103 : ///called at [GestureDetector.onHorizontalDragEnd] 104 1 : onDragEnd(DragEndDetails details) { 105 4 : Provider.of<LiquidProvider>(context, listen: false).updateSlide(SlideUpdate( 106 : SlideDirection.none, 107 1 : slidePercentHor, 108 1 : slidePercentVer, 109 : UpdateType.doneDragging, 110 : )); 111 : 112 : //Making dragStart to null for the reallocation 113 2 : slidePercentHor = slidePercentVer = 0; 114 1 : slideDirection = SlideDirection.none; 115 1 : dragStart = null; 116 : } 117 : 118 1 : @override 119 : void initState() { 120 1 : super.initState(); 121 3 : WidgetsBinding.instance!.addPostFrameCallback((_) { 122 2 : if (widget.slideIconWidget != null) 123 2 : Provider.of<LiquidProvider>(context, listen: false) 124 4 : .setIconSize(_keyIcon.currentContext!.size!); 125 : }); 126 : } 127 : 128 1 : @override 129 : Widget build(BuildContext context) { 130 : //Gesture Detector for horizontal drag 131 1 : final model = Provider.of<LiquidProvider>(context, listen: false); 132 : 133 1 : return GestureDetector( 134 : behavior: HitTestBehavior.translucent, 135 2 : onHorizontalDragStart: model.isInProgress ? null : onDragStart, 136 2 : onHorizontalDragUpdate: model.isInProgress ? null : onDragUpdate, 137 2 : onHorizontalDragEnd: model.isInProgress ? null : onDragEnd, 138 1 : child: Align( 139 1 : alignment: Alignment( 140 2 : 1 - slidePercentHor, 141 6 : -1.0 + Utils.handleIconAlignment(widget.iconPosition!) * 2, 142 : ), 143 1 : child: Opacity( 144 2 : opacity: 1 - slidePercentHor, 145 2 : child: slideDirection != SlideDirection.leftToRight && 146 2 : widget.slideIconWidget != null 147 1 : ? SizedBox( 148 1 : key: _keyIcon, 149 1 : child: Padding( 150 : padding: const EdgeInsets.symmetric( 151 : horizontal: 2.0, vertical: 10.0), 152 2 : child: widget.slideIconWidget, 153 : ), 154 : ) 155 : : null, 156 : ), 157 : )); 158 : } 159 : }