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