Line data Source code
1 : import 'dart:math';
2 : import 'dart:ui' show lerpDouble;
3 :
4 : import 'package:flutter/gestures.dart';
5 : import 'package:flutter/material.dart';
6 : import 'package:get/get.dart';
7 :
8 : import 'newroute/customTransition.dart';
9 : import 'newroute/transitions_component.dart';
10 : import 'newroute/transitions_filter.dart';
11 :
12 : class GetPageRoute<T> extends PageRouteBuilder<T> {
13 : final TransitionComponent transitionComponent;
14 : final Duration duration;
15 : final bool popGesture;
16 : final Transition transition;
17 : final Curve curve;
18 : final GetPageBuilder page;
19 : final CustomTransition customTransition;
20 : final Bindings binding;
21 : final Map<String, String> parameter;
22 : final List<Bindings> bindings;
23 :
24 1 : GetPageRoute({
25 : this.transitionComponent,
26 : RouteSettings settings,
27 : this.duration,
28 : this.transition,
29 : this.binding,
30 : @required this.page,
31 : this.bindings,
32 : this.opaque = true,
33 : this.parameter,
34 : this.fullscreenDialog = false,
35 : this.curve,
36 : this.popGesture,
37 : this.customTransition,
38 1 : }) : super(
39 2 : pageBuilder: (context, anim1, anim2) => page(),
40 : settings: settings,
41 : ) {
42 1 : if (binding != null) {
43 0 : binding.dependencies();
44 : }
45 1 : if (bindings != null) {
46 0 : for (Bindings element in bindings) {
47 0 : element.dependencies();
48 : }
49 : }
50 : }
51 :
52 : @override
53 : final bool opaque;
54 :
55 : @override
56 : final bool fullscreenDialog;
57 :
58 1 : @override
59 : Widget buildTransitions(BuildContext context, Animation<double> animation,
60 : Animation<double> secondaryAnimation, Widget child) {
61 1 : if (this.customTransition != null) {
62 0 : return this.customTransition.buildTransition(
63 : context,
64 : animation,
65 : secondaryAnimation,
66 0 : popGesture ?? Get.defaultPopGesture
67 0 : ? _CupertinoBackGestureDetector<T>(
68 0 : enabledCallback: () => _isPopGestureEnabled<T>(this),
69 0 : onStartPopGesture: () => _startPopGesture<T>(this),
70 : child: child)
71 : : child);
72 : }
73 :
74 2 : if (transition == Transition.native) {
75 0 : return Theme.of(context).pageTransitionsTheme.buildTransitions(
76 : this,
77 : context,
78 : animation,
79 : secondaryAnimation,
80 0 : GetPlatform.isIOS
81 0 : ? _CupertinoBackGestureDetector<T>(
82 0 : enabledCallback: () => _isPopGestureEnabled<T>(this),
83 0 : onStartPopGesture: () => _startPopGesture<T>(this),
84 : child: child)
85 : : child);
86 : }
87 :
88 1 : final curvedAnimation = CurvedAnimation(
89 : parent: animation,
90 1 : curve: this.curve ?? Curves.linear,
91 : );
92 :
93 1 : return TransitionFilter.newTransitionComponent(
94 2 : transition, transitionComponent)
95 1 : .buildChildWithTransition(
96 : context,
97 : curvedAnimation,
98 : secondaryAnimation,
99 3 : popGesture ?? Get.defaultPopGesture
100 0 : ? _CupertinoBackGestureDetector<T>(
101 0 : enabledCallback: () => _isPopGestureEnabled<T>(this),
102 0 : onStartPopGesture: () => _startPopGesture<T>(this),
103 : child: child)
104 : : child);
105 : }
106 :
107 1 : @override
108 : Duration get transitionDuration =>
109 1 : this.duration ?? Duration(milliseconds: 300);
110 :
111 0 : static bool _isPopGestureEnabled<T>(PageRoute<T> route) {
112 0 : if (route.isFirst) return false;
113 :
114 0 : if (route.willHandlePopInternally) return false;
115 :
116 0 : if (route.hasScopedWillPopCallback) return false;
117 :
118 0 : if (route.fullscreenDialog) return false;
119 :
120 0 : if (route.animation.status != AnimationStatus.completed) return false;
121 :
122 0 : if (route.secondaryAnimation.status != AnimationStatus.dismissed)
123 : return false;
124 :
125 0 : if (isPopGestureInProgress(route)) return false;
126 :
127 : return true;
128 : }
129 :
130 0 : static _CupertinoBackGestureController<T> _startPopGesture<T>(
131 : PageRoute<T> route) {
132 0 : assert(_isPopGestureEnabled(route));
133 :
134 0 : return _CupertinoBackGestureController<T>(
135 0 : navigator: route.navigator,
136 0 : controller: route.controller,
137 : );
138 : }
139 :
140 0 : static bool isPopGestureInProgress(PageRoute<dynamic> route) {
141 0 : return route.navigator.userGestureInProgress;
142 : }
143 :
144 0 : bool get popGestureInProgress => isPopGestureInProgress(this);
145 : }
146 :
147 : const double _kBackGestureWidth = 20.0;
148 : const double _kMinFlingVelocity = 1.0;
149 : const int _kMaxDroppedSwipePageForwardAnimationTime = 800; // Milliseconds.
150 :
151 : // The maximum time for a page to get reset to it's original position if the
152 : // user releases a page mid swipe.
153 : const int _kMaxPageBackAnimationTime = 300;
154 :
155 : class _CupertinoBackGestureDetector<T> extends StatefulWidget {
156 0 : const _CupertinoBackGestureDetector({
157 : Key key,
158 : @required this.enabledCallback,
159 : @required this.onStartPopGesture,
160 : @required this.child,
161 0 : }) : assert(enabledCallback != null),
162 0 : assert(onStartPopGesture != null),
163 0 : assert(child != null),
164 0 : super(key: key);
165 :
166 : final Widget child;
167 :
168 : final ValueGetter<bool> enabledCallback;
169 :
170 : final ValueGetter<_CupertinoBackGestureController<T>> onStartPopGesture;
171 :
172 0 : @override
173 : _CupertinoBackGestureDetectorState<T> createState() =>
174 0 : _CupertinoBackGestureDetectorState<T>();
175 : }
176 :
177 : class _CupertinoBackGestureDetectorState<T>
178 : extends State<_CupertinoBackGestureDetector<T>> {
179 : _CupertinoBackGestureController<T> _backGestureController;
180 :
181 : HorizontalDragGestureRecognizer _recognizer;
182 :
183 0 : @override
184 : void initState() {
185 0 : super.initState();
186 0 : _recognizer = HorizontalDragGestureRecognizer(debugOwner: this)
187 0 : ..onStart = _handleDragStart
188 0 : ..onUpdate = _handleDragUpdate
189 0 : ..onEnd = _handleDragEnd
190 0 : ..onCancel = _handleDragCancel;
191 : }
192 :
193 0 : @override
194 : void dispose() {
195 0 : _recognizer.dispose();
196 0 : super.dispose();
197 : }
198 :
199 0 : void _handleDragStart(DragStartDetails details) {
200 0 : assert(mounted);
201 0 : assert(_backGestureController == null);
202 0 : _backGestureController = widget.onStartPopGesture();
203 : }
204 :
205 0 : void _handleDragUpdate(DragUpdateDetails details) {
206 0 : assert(mounted);
207 0 : assert(_backGestureController != null);
208 0 : _backGestureController.dragUpdate(
209 0 : _convertToLogical(details.primaryDelta / context.size.width));
210 : }
211 :
212 0 : void _handleDragEnd(DragEndDetails details) {
213 0 : assert(mounted);
214 0 : assert(_backGestureController != null);
215 0 : _backGestureController.dragEnd(_convertToLogical(
216 0 : details.velocity.pixelsPerSecond.dx / context.size.width));
217 0 : _backGestureController = null;
218 : }
219 :
220 0 : void _handleDragCancel() {
221 0 : assert(mounted);
222 : // This can be called even if start is not called, paired with the "down" event
223 : // that we don't consider here.
224 0 : _backGestureController?.dragEnd(0.0);
225 0 : _backGestureController = null;
226 : }
227 :
228 0 : void _handlePointerDown(PointerDownEvent event) {
229 0 : if (widget.enabledCallback()) _recognizer.addPointer(event);
230 : }
231 :
232 0 : double _convertToLogical(double value) {
233 0 : switch (Directionality.of(context)) {
234 0 : case TextDirection.rtl:
235 0 : return -value;
236 0 : case TextDirection.ltr:
237 : return value;
238 : }
239 : return null;
240 : }
241 :
242 0 : @override
243 : Widget build(BuildContext context) {
244 0 : assert(debugCheckHasDirectionality(context));
245 : // For devices with notches, the drag area needs to be larger on the side
246 : // that has the notch.
247 0 : double dragAreaWidth = Directionality.of(context) == TextDirection.ltr
248 0 : ? MediaQuery.of(context).padding.left
249 0 : : MediaQuery.of(context).padding.right;
250 12 : dragAreaWidth = max(dragAreaWidth, _kBackGestureWidth);
251 0 : return Stack(
252 : fit: StackFit.passthrough,
253 0 : children: <Widget>[
254 0 : widget.child,
255 0 : PositionedDirectional(
256 : start: 0.0,
257 : width: dragAreaWidth,
258 : top: 0.0,
259 : bottom: 0.0,
260 0 : child: Listener(
261 0 : onPointerDown: _handlePointerDown,
262 : behavior: HitTestBehavior.translucent,
263 : ),
264 : ),
265 : ],
266 : );
267 : }
268 : }
269 :
270 : class _CupertinoBackGestureController<T> {
271 : /// Creates a controller for an iOS-style back gesture.
272 : ///
273 : /// The [navigator] and [controller] arguments must not be null.
274 0 : _CupertinoBackGestureController({
275 : @required this.navigator,
276 : @required this.controller,
277 0 : }) : assert(navigator != null),
278 0 : assert(controller != null) {
279 0 : navigator.didStartUserGesture();
280 : }
281 :
282 : final AnimationController controller;
283 : final NavigatorState navigator;
284 :
285 : /// The drag gesture has changed by [fractionalDelta]. The total range of the
286 : /// drag should be 0.0 to 1.0.
287 0 : void dragUpdate(double delta) {
288 0 : controller.value -= delta;
289 : }
290 :
291 : /// The drag gesture has ended with a horizontal motion of
292 : /// [fractionalVelocity] as a fraction of screen width per second.
293 0 : void dragEnd(double velocity) {
294 : // Fling in the appropriate direction.
295 : // AnimationController.fling is guaranteed to
296 : // take at least one frame.
297 : //
298 : // This curve has been determined through rigorously eyeballing native iOS
299 : // animations.
300 : const Curve animationCurve = Curves.fastLinearToSlowEaseIn;
301 : bool animateForward;
302 :
303 : // If the user releases the page before mid screen with sufficient velocity,
304 : // or after mid screen, we should animate the page out. Otherwise, the page
305 : // should be animated back in.
306 0 : if (velocity.abs() >= _kMinFlingVelocity)
307 0 : animateForward = velocity <= 0;
308 : else
309 0 : animateForward = controller.value > 0.5;
310 :
311 : if (animateForward) {
312 : // The closer the panel is to dismissing, the shorter the animation is.
313 : // We want to cap the animation time, but we want to use a linear curve
314 : // to determine it.
315 12 : final int droppedPageForwardAnimationTime = min(
316 0 : lerpDouble(
317 0 : _kMaxDroppedSwipePageForwardAnimationTime, 0, controller.value)
318 0 : .floor(),
319 : _kMaxPageBackAnimationTime,
320 : );
321 0 : controller.animateTo(1.0,
322 0 : duration: Duration(milliseconds: droppedPageForwardAnimationTime),
323 : curve: animationCurve);
324 : } else {
325 : // This route is destined to pop at this point. Reuse navigator's pop.
326 0 : navigator.pop();
327 :
328 : // The popping may have finished inline if already at the target destination.
329 0 : if (controller.isAnimating) {
330 : // Otherwise, use a custom popping animation duration and curve.
331 0 : final int droppedPageBackAnimationTime = lerpDouble(
332 0 : 0, _kMaxDroppedSwipePageForwardAnimationTime, controller.value)
333 0 : .floor();
334 0 : controller.animateBack(0.0,
335 0 : duration: Duration(milliseconds: droppedPageBackAnimationTime),
336 : curve: animationCurve);
337 : }
338 : }
339 :
340 0 : if (controller.isAnimating) {
341 : // Keep the userGestureInProgress in true state so we don't change the
342 : // curve of the page transition mid-flight since CupertinoPageTransition
343 : // depends on userGestureInProgress.
344 : AnimationStatusListener animationStatusCallback;
345 0 : animationStatusCallback = (AnimationStatus status) {
346 0 : navigator.didStopUserGesture();
347 0 : controller.removeStatusListener(animationStatusCallback);
348 : };
349 0 : controller.addStatusListener(animationStatusCallback);
350 : } else {
351 0 : navigator.didStopUserGesture();
352 : }
353 : }
354 : }
355 :
356 : // import 'package:flutter/cupertino.dart';
357 : // import 'package:flutter/foundation.dart';
358 : // import 'package:flutter/gestures.dart';
359 : // import 'package:flutter/material.dart';
360 : // import 'package:get/src/get_main.dart';
361 : // import 'package:get/src/routes/bindings_interface.dart';
362 :
363 : // import '../platform/platform.dart';
364 : // import 'transitions_type.dart';
365 :
366 : // const double _kBackGestureWidth = 20.0;
367 : // const double _kMinFlingVelocity = 1.0;
368 : // const int _kMaxDroppedSwipePageForwardAnimationTime = 800; // Milliseconds.
369 :
370 : // // The maximum time for a page to get reset to it's original position if the
371 : // // user releases a page mid swipe.
372 : // const int _kMaxPageBackAnimationTime = 300;
373 :
374 : // class GetPageRoute<T> extends PageRoute<T> {
375 : // /// The [builder], [maintainState], and [fullscreenDialog] arguments must not
376 : // /// be null.
377 : // GetPageRoute({
378 : // @required this.page,
379 : // this.title,
380 : // RouteSettings settings,
381 : // this.maintainState = true,
382 : // this.curve = Curves.linear,
383 : // this.alignment,
384 : // this.parameter,
385 : // this.binding,
386 : // this.route,
387 : // this.bindings,
388 : // this.customBuildPageTransitions,
389 : // this.opaque = true,
390 : // this.transitionDuration = const Duration(milliseconds: 400),
391 : // this.popGesture,
392 : // this.transition,
393 : // // this.duration = const Duration(milliseconds: 400),
394 : // bool fullscreenDialog = false,
395 : // }) : // assert(page != null),
396 : // assert(maintainState != null),
397 : // assert(fullscreenDialog != null),
398 : // // assert(opaque),
399 : // super(settings: settings, fullscreenDialog: fullscreenDialog) {
400 : // /// prebuild dependencies
401 : // if (binding != null) {
402 : // binding.dependencies();
403 : // }
404 : // if (bindings != null) {
405 : // bindings.forEach((element) => element.dependencies());
406 : // }
407 : // }
408 :
409 : // /// Builds the primary contents of the route.
410 : // final Widget page;
411 :
412 : // final GetPageBuilder route;
413 :
414 : // final Widget customBuildPageTransitions;
415 :
416 : // final bool popGesture;
417 :
418 : // final Bindings binding;
419 :
420 : // final List<Bindings> bindings;
421 :
422 : // // final Duration duration;
423 :
424 : // final Map<String, String> parameter;
425 :
426 : // final String title;
427 :
428 : // final Transition transition;
429 :
430 : // final Curve curve;
431 :
432 : // final Alignment alignment;
433 :
434 : // ValueNotifier<String> _previousTitle;
435 :
436 : // /// The title string of the previous [GetRoute].
437 : // ///
438 : // /// The [ValueListenable]'s value is readable after the route is installed
439 : // /// onto a [Navigator]. The [ValueListenable] will also notify its listeners
440 : // /// if the value changes (such as by replacing the previous route).
441 : // ///
442 : // /// The [ValueListenable] itself will be null before the route is installed.
443 : // /// Its content value will be null if the previous route has no title or
444 : // /// is not a [GetRoute].
445 : // ///
446 : // /// See also:
447 : // ///
448 : // /// * [ValueListenableBuilder], which can be used to listen and rebuild
449 : // /// widgets based on a ValueListenable.
450 : // ValueListenable<String> get previousTitle {
451 : // assert(
452 : // _previousTitle != null,
453 : // 'Cannot read the previousTitle for a route that has not yet been installed',
454 : // );
455 : // return _previousTitle;
456 : // }
457 :
458 : // @override
459 : // void didChangePrevious(Route<dynamic> previousRoute) {
460 : // final String previousTitleString =
461 : // previousRoute is GetPageRoute ? previousRoute.title : null;
462 : // if (_previousTitle == null) {
463 : // _previousTitle = ValueNotifier<String>(previousTitleString);
464 : // } else {
465 : // _previousTitle.value = previousTitleString;
466 : // }
467 : // super.didChangePrevious(previousRoute);
468 : // }
469 :
470 : // @override
471 : // final bool maintainState;
472 :
473 : // /// Allows you to set opaque to false to prevent route reconstruction.
474 : // @override
475 : // final bool opaque;
476 :
477 : // @override
478 : // final Duration transitionDuration;
479 :
480 : // @override
481 : // Color get barrierColor => null; //Color(0x00FFFFFF);
482 :
483 : // @override
484 : // String get barrierLabel => null;
485 :
486 : // @override
487 : // bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
488 : // // Don't perform outgoing animation if the next route is a fullscreen dialog.
489 : // return nextRoute is GetPageRoute && !nextRoute.fullscreenDialog;
490 : // }
491 :
492 : // /// True if an iOS-style back swipe pop gesture is currently underway for [route].
493 : // ///
494 : // /// This just check the route's [NavigatorState.userGestureInProgress].
495 : // ///
496 : // /// See also:
497 : // ///
498 : // /// * [popGestureEnabled], which returns true if a user-triggered pop gesture
499 : // /// would be allowed.
500 : // static bool isPopGestureInProgress(PageRoute<dynamic> route) {
501 : // return route.navigator.userGestureInProgress;
502 : // }
503 :
504 : // /// True if an iOS-style back swipe pop gesture is currently underway for this route.
505 : // ///
506 : // /// See also:
507 : // ///
508 : // /// * [isPopGestureInProgress], which returns true if a Cupertino pop gesture
509 : // /// is currently underway for specific route.
510 : // /// * [popGestureEnabled], which returns true if a user-triggered pop gesture
511 : // /// would be allowed.
512 : // bool get popGestureInProgress => isPopGestureInProgress(this);
513 :
514 : // /// Whether a pop gesture can be started by the user.
515 : // ///
516 : // /// Returns true if the user can edge-swipe to a previous route.
517 : // ///
518 : // /// Returns false once [isPopGestureInProgress] is true, but
519 : // /// [isPopGestureInProgress] can only become true if [popGestureEnabled] was
520 : // /// true first.
521 : // ///
522 : // /// This should only be used between frames, not during build.
523 : // bool get popGestureEnabled => _isPopGestureEnabled(this);
524 :
525 : // static bool _isPopGestureEnabled<T>(PageRoute<T> route) {
526 : // // If there's nothing to go back to, then obviously we don't support
527 : // // the back gesture.
528 : // if (route.isFirst) return false;
529 : // // If the route wouldn't actually pop if we popped it, then the gesture
530 : // // would be really confusing (or would skip internal routes), so disallow it.
531 : // if (route.willHandlePopInternally) return false;
532 : // // If attempts to dismiss this route might be vetoed such as in a page
533 : // // with forms, then do not allow the user to dismiss the route with a swipe.
534 : // if (route.hasScopedWillPopCallback) return false;
535 : // // Fullscreen dialogs aren't dismissible by back swipe.
536 : // if (route.fullscreenDialog) return false;
537 : // // If we're in an animation already, we cannot be manually swiped.
538 : // if (route.animation.status != AnimationStatus.completed) return false;
539 : // // If we're being popped into, we also cannot be swiped until the pop above
540 : // // it completes. This translates to our secondary animation being
541 : // // dismissed.
542 : // if (route.secondaryAnimation.status != AnimationStatus.dismissed)
543 : // return false;
544 : // // If we're in a gesture already, we cannot start another.
545 : // if (isPopGestureInProgress(route)) return false;
546 :
547 : // // Looks like a back gesture would be welcome!
548 : // return true;
549 : // }
550 :
551 : // @override
552 : // Widget buildPage(BuildContext context, Animation<double> animation,
553 : // Animation<double> secondaryAnimation) {
554 : // final Widget result = Semantics(
555 : // scopesRoute: true,
556 : // explicitChildNodes: true,
557 : // child: (route == null ? page : route()),
558 : // );
559 : // assert(() {
560 : // if (route == null && page == null) {
561 : // throw FlutterError.fromParts(<DiagnosticsNode>[
562 : // ErrorSummary(
563 : // 'The builder for route "${settings.name}" returned null.'),
564 : // ErrorDescription('Route builders must never return null.'),
565 : // ]);
566 : // }
567 : // return true;
568 : // }());
569 : // return result;
570 : // }
571 :
572 : // // Called by _CupertinoBackGestureDetector when a pop ("back") drag start
573 : // // gesture is detected. The returned controller handles all of the subsequent
574 : // // drag events.
575 : // static _CupertinoBackGestureController<T> _startPopGesture<T>(
576 : // PageRoute<T> route) {
577 : // assert(_isPopGestureEnabled(route));
578 :
579 : // return _CupertinoBackGestureController<T>(
580 : // navigator: route.navigator,
581 : // controller: route.controller, // protected access
582 : // );
583 : // }
584 :
585 : // /// Returns a [CupertinoFullscreenDialogTransition] if [route] is a full
586 : // /// screen dialog, otherwise a [CupertinoPageTransition] is returned.
587 : // ///
588 : // /// Used by [GetRoute.buildTransitions].
589 : // ///
590 : // /// This method can be applied to any [PageRoute], not just
591 : // /// [GetRoute]. It's typically used to provide a Cupertino style
592 : // /// horizontal transition for material widgets when the target platform
593 : // /// is [TargetPlatform.iOS].
594 : // ///
595 : // /// See also:
596 : // ///
597 : // /// * [CupertinoPageTransitionsBuilder], which uses this method to define a
598 : // /// [PageTransitionsBuilder] for the [PageTransitionsTheme].
599 : // Widget buildPageTransitions<T>(
600 : // PageRoute<T> route,
601 : // BuildContext context,
602 : // bool popGesture,
603 : // Animation<double> animation,
604 : // Animation<double> secondaryAnimation,
605 : // Widget child,
606 : // Transition tr,
607 : // Curve curve,
608 : // Alignment alignment,
609 : // ) {
610 : // Transition transition = (tr ?? Get.defaultTransition);
611 :
612 : // if (route.fullscreenDialog) {
613 : // final bool linearTransition = isPopGestureInProgress(route);
614 : // return CupertinoFullscreenDialogTransition(
615 : // primaryRouteAnimation: animation,
616 : // secondaryRouteAnimation: secondaryAnimation,
617 : // child: child,
618 : // linearTransition: linearTransition,
619 : // );
620 : // } else {
621 : // switch (transition) {
622 : // case Transition.fade:
623 : // final PageTransitionsBuilder matchingBuilder =
624 : // FadeUpwardsPageTransitionsBuilder();
625 : // return matchingBuilder.buildTransitions<T>(
626 : // route,
627 : // context,
628 : // animation,
629 : // secondaryAnimation,
630 : // popGesture
631 : // ? _CupertinoBackGestureDetector<T>(
632 : // enabledCallback: () => _isPopGestureEnabled<T>(route),
633 : // onStartPopGesture: () => _startPopGesture<T>(route),
634 : // child: child)
635 : // : child);
636 : // break;
637 : // case Transition.rightToLeft:
638 : // return SlideTransition(
639 : // transformHitTests: false,
640 : // position: new Tween<Offset>(
641 : // begin: const Offset(1.0, 0.0),
642 : // end: Offset.zero,
643 : // ).animate(animation),
644 : // child: new SlideTransition(
645 : // position: new Tween<Offset>(
646 : // begin: Offset.zero,
647 : // end: const Offset(-1.0, 0.0),
648 : // ).animate(secondaryAnimation),
649 : // child: popGesture
650 : // ? _CupertinoBackGestureDetector<T>(
651 : // enabledCallback: () => _isPopGestureEnabled<T>(route),
652 : // onStartPopGesture: () => _startPopGesture<T>(route),
653 : // child: child)
654 : // : child),
655 : // );
656 : // break;
657 : // case Transition.leftToRight:
658 : // return SlideTransition(
659 : // transformHitTests: false,
660 : // position: Tween<Offset>(
661 : // begin: const Offset(-1.0, 0.0),
662 : // end: Offset.zero,
663 : // ).animate(animation),
664 : // child: new SlideTransition(
665 : // position: new Tween<Offset>(
666 : // begin: Offset.zero,
667 : // end: const Offset(1.0, 0.0),
668 : // ).animate(secondaryAnimation),
669 : // child: popGesture
670 : // ? _CupertinoBackGestureDetector<T>(
671 : // enabledCallback: () => _isPopGestureEnabled<T>(route),
672 : // onStartPopGesture: () => _startPopGesture<T>(route),
673 : // child: child)
674 : // : child),
675 : // );
676 : // break;
677 : // case Transition.upToDown:
678 : // return SlideTransition(
679 : // transformHitTests: false,
680 : // position: Tween<Offset>(
681 : // begin: const Offset(0.0, -1.0),
682 : // end: Offset.zero,
683 : // ).animate(animation),
684 : // child: new SlideTransition(
685 : // position: new Tween<Offset>(
686 : // begin: Offset.zero,
687 : // end: const Offset(0.0, 1.0),
688 : // ).animate(secondaryAnimation),
689 : // child: popGesture
690 : // ? _CupertinoBackGestureDetector<T>(
691 : // enabledCallback: () => _isPopGestureEnabled<T>(route),
692 : // onStartPopGesture: () => _startPopGesture<T>(route),
693 : // child: child)
694 : // : child),
695 : // );
696 : // break;
697 : // case Transition.downToUp:
698 : // return SlideTransition(
699 : // transformHitTests: false,
700 : // position: Tween<Offset>(
701 : // begin: const Offset(0.0, 1.0),
702 : // end: Offset.zero,
703 : // ).animate(animation),
704 : // child: new SlideTransition(
705 : // position: new Tween<Offset>(
706 : // begin: Offset.zero,
707 : // end: const Offset(0.0, -1.0),
708 : // ).animate(secondaryAnimation),
709 : // child: popGesture
710 : // ? _CupertinoBackGestureDetector<T>(
711 : // enabledCallback: () => _isPopGestureEnabled<T>(route),
712 : // onStartPopGesture: () => _startPopGesture<T>(route),
713 : // child: child)
714 : // : child),
715 : // );
716 : // break;
717 :
718 : // case Transition.rightToLeftWithFade:
719 : // return SlideTransition(
720 : // position: Tween<Offset>(
721 : // begin: const Offset(1.0, 0.0),
722 : // end: Offset.zero,
723 : // ).animate(animation),
724 : // child: FadeTransition(
725 : // opacity: animation,
726 : // child: SlideTransition(
727 : // position: Tween<Offset>(
728 : // begin: Offset.zero,
729 : // end: const Offset(-1.0, 0.0),
730 : // ).animate(secondaryAnimation),
731 : // child: popGesture
732 : // ? _CupertinoBackGestureDetector<T>(
733 : // enabledCallback: () => _isPopGestureEnabled<T>(route),
734 : // onStartPopGesture: () => _startPopGesture<T>(route),
735 : // child: child)
736 : // : child),
737 : // ),
738 : // );
739 : // break;
740 : // case Transition.leftToRightWithFade:
741 : // return SlideTransition(
742 : // position: Tween<Offset>(
743 : // begin: const Offset(-1.0, 0.0),
744 : // end: Offset.zero,
745 : // ).animate(animation),
746 : // child: FadeTransition(
747 : // opacity: animation,
748 : // child: SlideTransition(
749 : // position: Tween<Offset>(
750 : // begin: Offset.zero,
751 : // end: const Offset(1.0, 0.0),
752 : // ).animate(secondaryAnimation),
753 : // child: popGesture
754 : // ? _CupertinoBackGestureDetector<T>(
755 : // enabledCallback: () => _isPopGestureEnabled<T>(route),
756 : // onStartPopGesture: () => _startPopGesture<T>(route),
757 : // child: child)
758 : // : child),
759 : // ),
760 : // );
761 : // break;
762 :
763 : // default:
764 : // return CupertinoPageTransition(
765 : // primaryRouteAnimation: animation,
766 : // secondaryRouteAnimation: secondaryAnimation,
767 : // // Check if the route has an animation that's currently participating
768 : // // in a back swipe gesture.
769 : // //
770 : // // In the middle of a back gesture drag, let the transition be linear to
771 : // // match finger motions.
772 : // linearTransition: isPopGestureInProgress(route),
773 : // child: popGesture
774 : // ? _CupertinoBackGestureDetector<T>(
775 : // enabledCallback: () => _isPopGestureEnabled<T>(route),
776 : // onStartPopGesture: () => _startPopGesture<T>(route),
777 : // child: child)
778 : // : child,
779 : // );
780 : // }
781 : // }
782 : // }
783 :
784 : // @override
785 : // Widget buildTransitions(BuildContext context, Animation<double> animation,
786 : // Animation<double> secondaryAnimation, Widget child) {
787 : // if (customBuildPageTransitions != null) {
788 : // return customBuildPageTransitions;
789 : // } else {
790 : // return buildPageTransitions<T>(
791 : // this,
792 : // context,
793 : // popGesture ?? GetPlatform.isIOS,
794 : // animation,
795 : // secondaryAnimation,
796 : // child,
797 : // transition,
798 : // curve,
799 : // alignment);
800 : // }
801 : // }
802 :
803 : // @override
804 : // String get debugLabel => '${super.debugLabel}(${settings.name})';
805 : // }
806 :
807 : // class _CupertinoBackGestureDetector<T> extends StatefulWidget {
808 : // const _CupertinoBackGestureDetector({
809 : // Key key,
810 : // @required this.enabledCallback,
811 : // @required this.onStartPopGesture,
812 : // @required this.child,
813 : // }) : assert(enabledCallback != null),
814 : // assert(onStartPopGesture != null),
815 : // assert(child != null),
816 : // super(key: key);
817 :
818 : // final Widget child;
819 :
820 : // final ValueGetter<bool> enabledCallback;
821 :
822 : // final ValueGetter<_CupertinoBackGestureController<T>> onStartPopGesture;
823 :
824 : // @override
825 : // _CupertinoBackGestureDetectorState<T> createState() =>
826 : // _CupertinoBackGestureDetectorState<T>();
827 : // }
828 :
829 : // class _CupertinoBackGestureDetectorState<T>
830 : // extends State<_CupertinoBackGestureDetector<T>> {
831 : // _CupertinoBackGestureController<T> _backGestureController;
832 :
833 : // HorizontalDragGestureRecognizer _recognizer;
834 :
835 : // @override
836 : // void initState() {
837 : // super.initState();
838 : // _recognizer = HorizontalDragGestureRecognizer(debugOwner: this)
839 : // ..onStart = _handleDragStart
840 : // ..onUpdate = _handleDragUpdate
841 : // ..onEnd = _handleDragEnd
842 : // ..onCancel = _handleDragCancel;
843 : // }
844 :
845 : // @override
846 : // void dispose() {
847 : // _recognizer.dispose();
848 : // super.dispose();
849 : // }
850 :
851 : // void _handleDragStart(DragStartDetails details) {
852 : // assert(mounted);
853 : // assert(_backGestureController == null);
854 : // _backGestureController = widget.onStartPopGesture();
855 : // }
856 :
857 : // void _handleDragUpdate(DragUpdateDetails details) {
858 : // assert(mounted);
859 : // assert(_backGestureController != null);
860 : // _backGestureController.dragUpdate(
861 : // _convertToLogical(details.primaryDelta / context.size.width));
862 : // }
863 :
864 : // void _handleDragEnd(DragEndDetails details) {
865 : // assert(mounted);
866 : // assert(_backGestureController != null);
867 : // _backGestureController.dragEnd(_convertToLogical(
868 : // details.velocity.pixelsPerSecond.dx / context.size.width));
869 : // _backGestureController = null;
870 : // }
871 :
872 : // void _handleDragCancel() {
873 : // assert(mounted);
874 : // // This can be called even if start is not called, paired with the "down" event
875 : // // that we don't consider here.
876 : // _backGestureController?.dragEnd(0.0);
877 : // _backGestureController = null;
878 : // }
879 :
880 : // void _handlePointerDown(PointerDownEvent event) {
881 : // if (widget.enabledCallback()) _recognizer.addPointer(event);
882 : // }
883 :
884 : // double _convertToLogical(double value) {
885 : // switch (Directionality.of(context)) {
886 : // case TextDirection.rtl:
887 : // return -value;
888 : // case TextDirection.ltr:
889 : // return value;
890 : // }
891 : // return null;
892 : // }
893 :
894 : // @override
895 : // Widget build(BuildContext context) {
896 : // assert(debugCheckHasDirectionality(context));
897 : // // For devices with notches, the drag area needs to be larger on the side
898 : // // that has the notch.
899 : // double dragAreaWidth = Directionality.of(context) == TextDirection.ltr
900 : // ? MediaQuery.of(context).padding.left
901 : // : MediaQuery.of(context).padding.right;
902 : // dragAreaWidth = max(dragAreaWidth, _kBackGestureWidth);
903 : // return Stack(
904 : // fit: StackFit.passthrough,
905 : // children: <Widget>[
906 : // widget.child,
907 : // PositionedDirectional(
908 : // start: 0.0,
909 : // width: dragAreaWidth,
910 : // top: 0.0,
911 : // bottom: 0.0,
912 : // child: Listener(
913 : // onPointerDown: _handlePointerDown,
914 : // behavior: HitTestBehavior.translucent,
915 : // ),
916 : // ),
917 : // ],
918 : // );
919 : // }
920 : // }
921 :
922 : // class _CupertinoBackGestureController<T> {
923 : // /// Creates a controller for an iOS-style back gesture.
924 : // ///
925 : // /// The [navigator] and [controller] arguments must not be null.
926 : // _CupertinoBackGestureController({
927 : // @required this.navigator,
928 : // @required this.controller,
929 : // }) : assert(navigator != null),
930 : // assert(controller != null) {
931 : // navigator.didStartUserGesture();
932 : // }
933 :
934 : // final AnimationController controller;
935 : // final NavigatorState navigator;
936 :
937 : // /// The drag gesture has changed by [fractionalDelta]. The total range of the
938 : // /// drag should be 0.0 to 1.0.
939 : // void dragUpdate(double delta) {
940 : // controller.value -= delta;
941 : // }
942 :
943 : // /// The drag gesture has ended with a horizontal motion of
944 : // /// [fractionalVelocity] as a fraction of screen width per second.
945 : // void dragEnd(double velocity) {
946 : // // Fling in the appropriate direction.
947 : // // AnimationController.fling is guaranteed to
948 : // // take at least one frame.
949 : // //
950 : // // This curve has been determined through rigorously eyeballing native iOS
951 : // // animations.
952 : // const Curve animationCurve = Curves.fastLinearToSlowEaseIn;
953 : // bool animateForward;
954 :
955 : // // If the user releases the page before mid screen with sufficient velocity,
956 : // // or after mid screen, we should animate the page out. Otherwise, the page
957 : // // should be animated back in.
958 : // if (velocity.abs() >= _kMinFlingVelocity)
959 : // animateForward = velocity <= 0;
960 : // else
961 : // animateForward = controller.value > 0.5;
962 :
963 : // if (animateForward) {
964 : // // The closer the panel is to dismissing, the shorter the animation is.
965 : // // We want to cap the animation time, but we want to use a linear curve
966 : // // to determine it.
967 : // final int droppedPageForwardAnimationTime = min(
968 : // lerpDouble(
969 : // _kMaxDroppedSwipePageForwardAnimationTime, 0, controller.value)
970 : // .floor(),
971 : // _kMaxPageBackAnimationTime,
972 : // );
973 : // controller.animateTo(1.0,
974 : // duration: Duration(milliseconds: droppedPageForwardAnimationTime),
975 : // curve: animationCurve);
976 : // } else {
977 : // // This route is destined to pop at this point. Reuse navigator's pop.
978 : // navigator.pop();
979 :
980 : // // The popping may have finished inline if already at the target destination.
981 : // if (controller.isAnimating) {
982 : // // Otherwise, use a custom popping animation duration and curve.
983 : // final int droppedPageBackAnimationTime = lerpDouble(
984 : // 0, _kMaxDroppedSwipePageForwardAnimationTime, controller.value)
985 : // .floor();
986 : // controller.animateBack(0.0,
987 : // duration: Duration(milliseconds: droppedPageBackAnimationTime),
988 : // curve: animationCurve);
989 : // }
990 : // }
991 :
992 : // if (controller.isAnimating) {
993 : // // Keep the userGestureInProgress in true state so we don't change the
994 : // // curve of the page transition mid-flight since CupertinoPageTransition
995 : // // depends on userGestureInProgress.
996 : // AnimationStatusListener animationStatusCallback;
997 : // animationStatusCallback = (AnimationStatus status) {
998 : // navigator.didStopUserGesture();
999 : // controller.removeStatusListener(animationStatusCallback);
1000 : // };
1001 : // controller.addStatusListener(animationStatusCallback);
1002 : // } else {
1003 : // navigator.didStopUserGesture();
1004 : // }
1005 : // }
1006 : // }
|