app.dart 6.81 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/rendering.dart';
6
import 'package:flutter/widgets.dart';
7

8
import 'colors.dart';
9
import 'page.dart';
10
import 'theme.dart';
11

12 13
export 'dart:ui' show Locale;

14 15 16 17 18
const TextStyle _errorTextStyle = const TextStyle(
  color: const Color(0xD0FF0000),
  fontFamily: 'monospace',
  fontSize: 48.0,
  fontWeight: FontWeight.w900,
19
  decoration: TextDecoration.underline,
20
  decorationColor: const Color(0xFFFFFF00),
21 22 23
  decorationStyle: TextDecorationStyle.double
);

24 25 26
/// An application that uses material design.
///
/// A convenience widget that wraps a number of widgets that are commonly
27
/// required for material design applications. It builds upon a
28 29
/// [WidgetsApp] by adding material-design specific functionality, such as
/// [AnimatedTheme] and [GridPaper]. This widget also configures the top-level
30
/// [Navigator]'s observer to perform [Hero] animations.
31 32 33 34 35 36
///
/// See also:
///
///  * [WidgetsApp]
///  * [Scaffold]
///  * [MaterialPageRoute]
37 38
class MaterialApp extends StatefulWidget {

39 40 41 42 43 44
  /// Creates a MaterialApp.
  ///
  /// At least one of [home], [routes], or [onGenerateRoute] must be
  /// given. If only [routes] is given, it must include an entry for
  /// the [Navigator.defaultRouteName] (`'/'`).
  ///
45
  /// This class creates an instance of [WidgetsApp].
Adam Barth's avatar
Adam Barth committed
46
  MaterialApp({
47
    Key key,
48 49 50 51 52 53
    this.title,
    this.theme,
    this.home,
    this.routes: const <String, WidgetBuilder>{},
    this.onGenerateRoute,
    this.onLocaleChanged,
54
    this.debugShowMaterialGrid: false,
55 56 57 58
    this.showPerformanceOverlay: false,
    this.showSemanticsDebugger: false,
    this.debugShowCheckedModeBanner: true
  }) : super(key: key) {
Ian Hickson's avatar
Ian Hickson committed
59
    assert(debugShowMaterialGrid != null);
60 61 62
    assert(routes != null);
    assert(!routes.containsKey(Navigator.defaultRouteName) || (home == null));
    assert(routes.containsKey(Navigator.defaultRouteName) || (home != null) || (onGenerateRoute != null));
63 64 65
 }
  /// A one-line description of this app for use in the window manager.
  final String title;
66

67
  /// The colors to use for the application's widgets.
68
  final ThemeData theme;
69

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
  /// The widget for the default route of the app
  /// ([Navigator.defaultRouteName], which is `'/'`).
  ///
  /// This is the page that is displayed first when the application is
  /// started normally.
  ///
  /// To be able to directly call [Theme.of], [MediaQuery.of],
  /// [LocaleQuery.of], etc, in the code sets the [home] argument in
  /// the constructor, you can use a [Builder] widget to get a
  /// [BuildContext].
  ///
  /// If this is not specified, then either the route with name `'/'`
  /// must be given in [routes], or the [onGenerateRoute] callback
  /// must be able to build a widget for that route.
  final Widget home;

86 87 88 89 90 91
  /// The application's top-level routing table.
  ///
  /// When a named route is pushed with [Navigator.pushNamed], the route name is
  /// looked up in this map. If the name is present, the associated
  /// [WidgetBuilder] is used to construct a [MaterialPageRoute] that performs
  /// an appropriate transition, including [Hero] animations, to the new route.
92 93 94 95 96 97 98 99 100
  ///
  /// If the app only has one page, then you can specify it using [home] instead.
  ///
  /// If [home] is specified, then it is an error to provide a route
  /// in this map for the [Navigator.defaultRouteName] route (`'/'`).
  ///
  /// If a route is requested that is not specified in this table (or
  /// by [home]), then the [onGenerateRoute] callback is invoked to
  /// build the page instead.
Ian Hickson's avatar
Ian Hickson committed
101 102
  final Map<String, WidgetBuilder> routes;

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
  /// The route generator callback used when the app is navigated to a
  /// named route.
  final RouteFactory onGenerateRoute;

  /// Callback that is invoked when the operating system changes the
  /// current locale.
  final LocaleChangedCallback onLocaleChanged;

  /// Turns on a performance overlay.
  /// https://flutter.io/debugging/#performanceoverlay
  final bool showPerformanceOverlay;

  /// Turns on an overlay that shows the accessibility information
  /// reported by the framework.
  final bool showSemanticsDebugger;

  /// Turns on a little "SLOW MODE" banner in checked mode to indicate
  /// that the app is in checked mode. This is on by default (in
  /// checked mode), to turn it off, set the constructor argument to
  /// false. In release mode this has no effect.
  ///
  /// To get this banner in your application if you're not using
  /// WidgetsApp, include a [CheckedModeBanner] widget in your app.
  ///
  /// This banner is intended to deter people from complaining that your
  /// app is slow when it's in checked mode. In checked mode, Flutter
  /// enables a large number of expensive diagnostics to aid in
  /// development, and so performance in checked mode is not
  /// representative of what will happen in release mode.
  final bool debugShowCheckedModeBanner;

134 135 136 137
  /// Turns on a [GridPaper] overlay that paints a baseline grid
  /// Material apps:
  /// https://www.google.com/design/spec/layout/metrics-keylines.html
  /// Only available in checked mode.
Ian Hickson's avatar
Ian Hickson committed
138
  final bool debugShowMaterialGrid;
139

140
  @override
Adam Barth's avatar
Adam Barth committed
141
  _MaterialAppState createState() => new _MaterialAppState();
142 143
}

144
class _MaterialAppState extends State<MaterialApp> {
Adam Barth's avatar
Adam Barth committed
145
  final HeroController _heroController = new HeroController();
146

147 148 149 150 151 152 153 154 155 156 157 158 159 160
  Route<dynamic> _onGenerateRoute(RouteSettings settings) {
    WidgetBuilder builder = config.routes[settings.name];
    if (builder == null && config.home != null && settings.name == Navigator.defaultRouteName)
      builder = (BuildContext context) => config.home;
    if (builder != null) {
      return new MaterialPageRoute<Null>(
        builder: builder,
        settings: settings
      );
    }
    if (config.onGenerateRoute != null)
      return config.onGenerateRoute(settings);
    return null;
  }
161

162
  @override
163
  Widget build(BuildContext context) {
164
    ThemeData theme = config.theme ?? new ThemeData.fallback();
165 166
    Widget result = new AnimatedTheme(
      data: theme,
167 168 169 170 171 172 173 174 175 176 177
      child: new WidgetsApp(
        title: config.title,
        textStyle: _errorTextStyle,
        color: theme?.primaryColor ?? Colors.blue[500], // blue[500] is the primary color of the default theme
        navigatorObserver: _heroController,
        onGenerateRoute: _onGenerateRoute,
        onLocaleChanged: config.onLocaleChanged,
        showPerformanceOverlay: config.showPerformanceOverlay,
        showSemanticsDebugger: config.showSemanticsDebugger,
        debugShowCheckedModeBanner: config.debugShowCheckedModeBanner
      )
178
    );
179

Ian Hickson's avatar
Ian Hickson committed
180 181 182 183 184 185 186 187 188 189 190 191
    assert(() {
      if (config.debugShowMaterialGrid) {
        result = new GridPaper(
          color: const Color(0xE0F9BBE0),
          interval: 8.0,
          divisions: 2,
          subDivisions: 1,
          child: result
        );
      }
      return true;
    });
192

Ian Hickson's avatar
Ian Hickson committed
193
    return result;
194
  }
195
}