page.dart 3.79 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:flutter/cupertino.dart';
6
import 'package:flutter/widgets.dart';
7

8
import 'page_transitions_theme.dart';
9
import 'theme.dart';
10

11 12
/// A modal route that replaces the entire screen with a platform-adaptive
/// transition.
13
///
14 15
/// For Android, the entrance transition for the page slides the page upwards
/// and fades it in. The exit transition is the same, but in reverse.
16
///
17 18 19
/// The transition is adaptive to the platform and on iOS, the page slides in
/// from the right and exits in reverse. The page also shifts to the left in
/// parallax when another page enters to cover it. (These directions are flipped
20
/// in environments with a right-to-left reading direction.)
21
///
22 23 24
/// By default, when a modal route is replaced by another, the previous route
/// remains in memory. To free all the resources when this is not necessary, set
/// [maintainState] to false.
25
///
26 27 28
/// The `fullscreenDialog` property specifies whether the incoming page is a
/// fullscreen modal dialog. On iOS, those pages animate from the bottom to the
/// top rather than horizontally.
29
///
30
/// The type `T` specifies the return type of the route which can be supplied as
31 32
/// the route is popped from the stack via [Navigator.pop] by providing the
/// optional `result` argument.
33
///
34 35
/// See also:
///
36 37
///  * [PageTransitionsTheme], which defines the default page transitions used
///    by [MaterialPageRoute.buildTransitions].
Hixie's avatar
Hixie committed
38
class MaterialPageRoute<T> extends PageRoute<T> {
39 40 41 42
  /// Construct a MaterialPageRoute whose contents are defined by [builder].
  ///
  /// The values of [builder], [maintainState], and [fullScreenDialog] must not
  /// be null.
43
  MaterialPageRoute({
44
    @required this.builder,
45
    RouteSettings settings,
46 47
    this.maintainState = true,
    bool fullscreenDialog = false,
48
  }) : assert(builder != null),
49 50
       assert(maintainState != null),
       assert(fullscreenDialog != null),
51 52
       assert(opaque),
       super(settings: settings, fullscreenDialog: fullscreenDialog);
53

54
  /// Builds the primary contents of the route.
55
  final WidgetBuilder builder;
Adam Barth's avatar
Adam Barth committed
56

57 58 59
  @override
  final bool maintainState;

60
  @override
61
  Duration get transitionDuration => const Duration(milliseconds: 300);
62 63

  @override
64
  Color get barrierColor => null;
65

66 67 68
  @override
  String get barrierLabel => null;

69
  @override
70
  bool canTransitionFrom(TransitionRoute<dynamic> previousRoute) {
71
    return previousRoute is MaterialPageRoute || previousRoute is CupertinoPageRoute;
72 73
  }

74 75 76
  @override
  bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
    // Don't perform outgoing animation if the next route is a fullscreen dialog.
77 78
    return (nextRoute is MaterialPageRoute && !nextRoute.fullscreenDialog)
        || (nextRoute is CupertinoPageRoute && !nextRoute.fullscreenDialog);
79 80
  }

81
  @override
82 83 84 85 86
  Widget buildPage(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
  ) {
87
    final Widget result = builder(context);
88
    assert(() {
89
      if (result == null) {
90
        throw FlutterError(
91 92 93 94
          'The builder for route "${settings.name}" returned null.\n'
          'Route builders must never return null.'
        );
      }
95
      return true;
96
    }());
97 98 99 100 101
    return Semantics(
      scopesRoute: true,
      explicitChildNodes: true,
      child: result,
    );
102 103
  }

104
  @override
105
  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
106 107
    final PageTransitionsTheme theme = Theme.of(context).pageTransitionsTheme;
    return theme.buildTransitions<T>(this, context, animation, secondaryAnimation, child);
108 109
  }

110
  @override
111 112
  String get debugLabel => '${super.debugLabel}(${settings.name})';
}