mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Create a CupertinoApp (#18469)
This commit is contained in:
parent
aad1bb4b59
commit
06f63aaa5a
@ -1 +1 @@
|
||||
bc99a4bdea0533994b34bc49f160af75f4904952
|
||||
413041fd6bbedd1c8bc6ca0b6ea6ea948079b669
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
library cupertino;
|
||||
|
||||
export 'src/cupertino/activity_indicator.dart';
|
||||
export 'src/cupertino/app.dart';
|
||||
export 'src/cupertino/bottom_tab_bar.dart';
|
||||
export 'src/cupertino/button.dart';
|
||||
export 'src/cupertino/colors.dart';
|
||||
|
||||
405
packages/flutter/lib/src/cupertino/app.dart
Normal file
405
packages/flutter/lib/src/cupertino/app.dart
Normal file
@ -0,0 +1,405 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'button.dart';
|
||||
import 'colors.dart';
|
||||
import 'icons.dart';
|
||||
import 'tab_view.dart';
|
||||
|
||||
// Based on specs from https://developer.apple.com/design/resources/ for
|
||||
// iOS 12.
|
||||
const TextStyle _kDefaultTextStyle = const TextStyle(
|
||||
fontFamily: '.SF Pro Text',
|
||||
fontSize: 17.0,
|
||||
letterSpacing: -0.38,
|
||||
color: CupertinoColors.black,
|
||||
decoration: TextDecoration.none,
|
||||
);
|
||||
|
||||
/// An application that uses Cupertino design.
|
||||
///
|
||||
/// A convenience widget that wraps a number of widgets that are commonly
|
||||
/// required for an iOS-design targeting application. It builds upon a
|
||||
/// [WidgetsApp] by iOS specific defaulting such as fonts and scrolling
|
||||
/// physics.
|
||||
///
|
||||
/// The [CupertinoApp] configures the top-level [Navigator] to search for routes
|
||||
/// in the following order:
|
||||
///
|
||||
/// 1. For the `/` route, the [home] property, if non-null, is used.
|
||||
///
|
||||
/// 2. Otherwise, the [routes] table is used, if it has an entry for the route.
|
||||
///
|
||||
/// 3. Otherwise, [onGenerateRoute] is called, if provided. It should return a
|
||||
/// non-null value for any _valid_ route not handled by [home] and [routes].
|
||||
///
|
||||
/// 4. Finally if all else fails [onUnknownRoute] is called.
|
||||
///
|
||||
/// If [home], [routes], [onGenerateRoute], and [onUnknownRoute] are all null,
|
||||
/// and [builder] is not null, then no [Navigator] is created.
|
||||
///
|
||||
/// Using this widget with caution on Android since it may produce behaviors
|
||||
/// Android users are not expecting such as:
|
||||
///
|
||||
/// * Pages will be dismissible via a back swipe.
|
||||
/// * Scrolling past extremities will trigger iOS-style spring overscrolls.
|
||||
/// * The San Francisco font family is unavailable on Android and can result
|
||||
/// in undefined font behavior.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [CupertinoPageScaffold], which provides a standard page layout default
|
||||
/// with nav bars.
|
||||
/// * [Navigator], which is used to manage the app's stack of pages.
|
||||
/// * [CupertinoPageRoute], which defines an app page that transitions in an
|
||||
/// iOS-specific way.
|
||||
/// * [WidgetsApp], which defines the basic app elements but does not depend
|
||||
/// on the Cupertino library.
|
||||
class CupertinoApp extends StatefulWidget {
|
||||
/// Creates a CupertinoApp.
|
||||
///
|
||||
/// At least one of [home], [routes], [onGenerateRoute], or [builder] must be
|
||||
/// non-null. If only [routes] is given, it must include an entry for the
|
||||
/// [Navigator.defaultRouteName] (`/`), since that is the route used when the
|
||||
/// application is launched with an intent that specifies an otherwise
|
||||
/// unsupported route.
|
||||
///
|
||||
/// This class creates an instance of [WidgetsApp].
|
||||
///
|
||||
/// The boolean arguments, [routes], and [navigatorObservers], must not be null.
|
||||
CupertinoApp({ // can't be const because the asserts use methods on Map :-(
|
||||
Key key,
|
||||
this.home,
|
||||
this.routes = const <String, WidgetBuilder>{},
|
||||
this.initialRoute,
|
||||
this.onGenerateRoute,
|
||||
this.onUnknownRoute,
|
||||
this.navigatorObservers = const <NavigatorObserver>[],
|
||||
this.builder,
|
||||
this.title = '',
|
||||
this.onGenerateTitle,
|
||||
this.color,
|
||||
this.locale,
|
||||
this.localizationsDelegates,
|
||||
this.localeResolutionCallback,
|
||||
this.supportedLocales = const <Locale>[const Locale('en', 'US')],
|
||||
this.showPerformanceOverlay = false,
|
||||
this.checkerboardRasterCacheImages = false,
|
||||
this.checkerboardOffscreenLayers = false,
|
||||
this.showSemanticsDebugger = false,
|
||||
this.debugShowCheckedModeBanner = true,
|
||||
}) : assert(routes != null),
|
||||
assert(navigatorObservers != null),
|
||||
assert(
|
||||
home == null ||
|
||||
!routes.containsKey(Navigator.defaultRouteName),
|
||||
'If the home property is specified, the routes table '
|
||||
'cannot include an entry for "/", since it would be redundant.'
|
||||
),
|
||||
assert(
|
||||
builder != null ||
|
||||
home != null ||
|
||||
routes.containsKey(Navigator.defaultRouteName) ||
|
||||
onGenerateRoute != null ||
|
||||
onUnknownRoute != null,
|
||||
'Either the home property must be specified, '
|
||||
'or the routes table must include an entry for "/", '
|
||||
'or there must be on onGenerateRoute callback specified, '
|
||||
'or there must be an onUnknownRoute callback specified, '
|
||||
'or the builder property must be specified, '
|
||||
'because otherwise there is nothing to fall back on if the '
|
||||
'app is started with an intent that specifies an unknown route.'
|
||||
),
|
||||
assert(
|
||||
(home != null ||
|
||||
routes.isNotEmpty ||
|
||||
onGenerateRoute != null ||
|
||||
onUnknownRoute != null)
|
||||
||
|
||||
(builder != null &&
|
||||
initialRoute == null &&
|
||||
navigatorObservers.isEmpty),
|
||||
'If no route is provided using '
|
||||
'home, routes, onGenerateRoute, or onUnknownRoute, '
|
||||
'a non-null callback for the builder property must be provided, '
|
||||
'and the other navigator-related properties, '
|
||||
'navigatorKey, initialRoute, and navigatorObservers, '
|
||||
'must have their initial values '
|
||||
'(null, null, and the empty list, respectively).'
|
||||
),
|
||||
assert(title != null),
|
||||
assert(showPerformanceOverlay != null),
|
||||
assert(checkerboardRasterCacheImages != null),
|
||||
assert(checkerboardOffscreenLayers != null),
|
||||
assert(showSemanticsDebugger != null),
|
||||
assert(debugShowCheckedModeBanner != null),
|
||||
super(key: key);
|
||||
|
||||
/// The widget for the default route of the app ([Navigator.defaultRouteName],
|
||||
/// which is `/`).
|
||||
///
|
||||
/// This is the route that is displayed first when the application is started
|
||||
/// normally, unless [initialRoute] is specified. It's also the route that's
|
||||
/// displayed if the [initialRoute] can't be displayed.
|
||||
///
|
||||
/// To be able to directly call [MediaQuery.of], [Navigator.of], etc, in the
|
||||
/// code that sets the [home] argument in the constructor, you can use a
|
||||
/// [Builder] widget to get a [BuildContext].
|
||||
///
|
||||
/// If [home] is specified, then [routes] must not include an entry for `/`,
|
||||
/// as [home] takes its place.
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
/// [builder] must not be null.
|
||||
///
|
||||
/// The difference between using [home] and using [builder] is that the [home]
|
||||
/// subtree is inserted into the application below a [Navigator] (and thus
|
||||
/// below an [Overlay], which [Navigator] uses). With [home], therefore,
|
||||
/// dialog boxes will work automatically, the [routes] table will be used, and
|
||||
/// APIs such as [Navigator.push] and [Navigator.pop] will work as expected.
|
||||
/// In contrast, the widget returned from [builder] is inserted _above_ the
|
||||
/// [CupertinoApp]'s [Navigator] (if any).
|
||||
final Widget home;
|
||||
|
||||
/// 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 [CupertinoPageRoute] that performs
|
||||
/// an appropriate transition to the new route.
|
||||
///
|
||||
/// If the app only has one page, then you can specify it using [home] instead.
|
||||
///
|
||||
/// If [home] is specified, then it implies an entry in this table for the
|
||||
/// [Navigator.defaultRouteName] route (`/`), and it is an error to
|
||||
/// redundantly provide such a route in the [routes] table.
|
||||
///
|
||||
/// If a route is requested that is not specified in this table (or by
|
||||
/// [home]), then the [onGenerateRoute] callback is called to build the page
|
||||
/// instead.
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
/// [builder] must not be null.
|
||||
final Map<String, WidgetBuilder> routes;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.initialRoute}
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
/// [initialRoute] must be null and [builder] must not be null.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Navigator.initialRoute], which is used to implement this property.
|
||||
/// * [Navigator.push], for pushing additional routes.
|
||||
/// * [Navigator.pop], for removing a route from the stack.
|
||||
final String initialRoute;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.onGenerateRoute}
|
||||
///
|
||||
/// This is used if [routes] does not contain the requested route.
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
/// [builder] must not be null.
|
||||
final RouteFactory onGenerateRoute;
|
||||
|
||||
/// Called when [onGenerateRoute] fails to generate a route, except for the
|
||||
/// [initialRoute].
|
||||
///
|
||||
/// {@macro flutter.widgets.widgetsApp.onUnknownRoute}
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
/// [builder] must not be null.
|
||||
final RouteFactory onUnknownRoute;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.navigatorObservers}
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
/// [navigatorObservers] must be the empty list and [builder] must not be null.
|
||||
final List<NavigatorObserver> navigatorObservers;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.builder}
|
||||
///
|
||||
/// If no routes are provided using [home], [routes], [onGenerateRoute], or
|
||||
/// [onUnknownRoute], the `child` will be null, and it is the responsibility
|
||||
/// of the [builder] to provide the application's routing machinery.
|
||||
///
|
||||
/// If routes _are_ provided using one or more of those properties, then
|
||||
/// `child` is not null, and the returned value should include the `child` in
|
||||
/// the widget subtree; if it does not, then the application will have no
|
||||
/// navigator and the [navigatorKey], [home], [routes], [onGenerateRoute],
|
||||
/// [onUnknownRoute], [initialRoute], and [navigatorObservers] properties will
|
||||
/// have no effect.
|
||||
///
|
||||
/// If [builder] is null, it is as if a builder was specified that returned
|
||||
/// the `child` directly. If it is null, routes must be provided using one of
|
||||
/// the other properties listed above.
|
||||
///
|
||||
/// Unless a [Navigator] is provided, either implicitly from [builder] being
|
||||
/// null, or by a [builder] including its `child` argument, or by a [builder]
|
||||
/// explicitly providing a [Navigator] of its own, APIs such as
|
||||
/// [Navigator.push] and [Navigator.pop], will not function.
|
||||
final TransitionBuilder builder;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.title}
|
||||
///
|
||||
/// This value is passed unmodified to [WidgetsApp.title].
|
||||
final String title;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.onGenerateTitle}
|
||||
///
|
||||
/// This value is passed unmodified to [WidgetsApp.onGenerateTitle].
|
||||
final GenerateAppTitle onGenerateTitle;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.color}
|
||||
final Color color;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.locale}
|
||||
final Locale locale;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.localizationsDelegates}
|
||||
final Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.localeResolutionCallback}
|
||||
///
|
||||
/// This callback is passed along to the [WidgetsApp] built by this widget.
|
||||
final LocaleResolutionCallback localeResolutionCallback;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.supportedLocales}
|
||||
///
|
||||
/// It is passed along unmodified to the [WidgetsApp] built by this widget.
|
||||
final Iterable<Locale> supportedLocales;
|
||||
|
||||
/// Turns on a performance overlay.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * <https://flutter.io/debugging/#performanceoverlay>
|
||||
final bool showPerformanceOverlay;
|
||||
|
||||
/// Turns on checkerboarding of raster cache images.
|
||||
final bool checkerboardRasterCacheImages;
|
||||
|
||||
/// Turns on checkerboarding of layers rendered to offscreen bitmaps.
|
||||
final bool checkerboardOffscreenLayers;
|
||||
|
||||
/// Turns on an overlay that shows the accessibility information
|
||||
/// reported by the framework.
|
||||
final bool showSemanticsDebugger;
|
||||
|
||||
/// {@macro flutter.widgets.widgetsApp.debugShowCheckedModeBanner}
|
||||
final bool debugShowCheckedModeBanner;
|
||||
|
||||
@override
|
||||
_CupertinoAppState createState() => new _CupertinoAppState();
|
||||
}
|
||||
|
||||
class _AlwaysCupertinoScrollBehavior extends ScrollBehavior {
|
||||
@override
|
||||
Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) {
|
||||
// Never build any overscroll glow indicators.
|
||||
return child;
|
||||
}
|
||||
|
||||
@override
|
||||
ScrollPhysics getScrollPhysics(BuildContext context) {
|
||||
return const BouncingScrollPhysics();
|
||||
}
|
||||
}
|
||||
|
||||
class _CupertinoAppState extends State<CupertinoApp> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_updateNavigator();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(CupertinoApp oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
_updateNavigator();
|
||||
}
|
||||
|
||||
bool _haveNavigator;
|
||||
void _updateNavigator() {
|
||||
_haveNavigator = widget.home != null ||
|
||||
widget.routes.isNotEmpty ||
|
||||
widget.onGenerateRoute != null ||
|
||||
widget.onUnknownRoute != null;
|
||||
}
|
||||
|
||||
Widget defaultBuilder(BuildContext context, Widget child) {
|
||||
// The `child` coming back out from WidgetsApp will always be null since
|
||||
// we never passed in anything for it to create a Navigator inside
|
||||
// WidgetsApp.
|
||||
assert(child == null);
|
||||
if (_haveNavigator) {
|
||||
// Reuse CupertinoTabView which creates a routing Navigator for us.
|
||||
final Widget navigator = new CupertinoTabView(
|
||||
builder: widget.home != null
|
||||
? (BuildContext context) => widget.home
|
||||
: null,
|
||||
routes: widget.routes,
|
||||
onGenerateRoute: widget.onGenerateRoute,
|
||||
onUnknownRoute: widget.onUnknownRoute,
|
||||
navigatorObservers: widget.navigatorObservers,
|
||||
);
|
||||
if (widget.builder != null) {
|
||||
return widget.builder(context, navigator);
|
||||
} else {
|
||||
return navigator;
|
||||
}
|
||||
} else {
|
||||
// We asserted that child is null above.
|
||||
return widget.builder(context, null);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new ScrollConfiguration(
|
||||
behavior: new _AlwaysCupertinoScrollBehavior(),
|
||||
child: new WidgetsApp(
|
||||
key: new GlobalObjectKey(this),
|
||||
// We're passing in a builder and nothing else that the WidgetsApp uses
|
||||
// to build its own Navigator because we're building a Navigator with
|
||||
// routes in this class.
|
||||
builder: defaultBuilder,
|
||||
title: widget.title,
|
||||
onGenerateTitle: widget.onGenerateTitle,
|
||||
textStyle: _kDefaultTextStyle,
|
||||
color: widget.color ?? CupertinoColors.activeBlue,
|
||||
locale: widget.locale,
|
||||
localizationsDelegates: widget.localizationsDelegates,
|
||||
localeResolutionCallback: widget.localeResolutionCallback,
|
||||
supportedLocales: widget.supportedLocales,
|
||||
showPerformanceOverlay: widget.showPerformanceOverlay,
|
||||
checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages,
|
||||
checkerboardOffscreenLayers: widget.checkerboardOffscreenLayers,
|
||||
showSemanticsDebugger: widget.showSemanticsDebugger,
|
||||
debugShowCheckedModeBanner: widget.debugShowCheckedModeBanner,
|
||||
inspectorSelectButtonBuilder: (BuildContext context, VoidCallback onPressed) {
|
||||
return new CupertinoButton(
|
||||
child: const Icon(
|
||||
CupertinoIcons.search,
|
||||
size: 28.0,
|
||||
color: CupertinoColors.white,
|
||||
),
|
||||
color: CupertinoColors.activeBlue,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -218,20 +218,7 @@ class MaterialApp extends StatefulWidget {
|
||||
/// [builder] must not be null.
|
||||
final Map<String, WidgetBuilder> routes;
|
||||
|
||||
/// The name of the first route to show, if a [Navigator] is built.
|
||||
///
|
||||
/// Defaults to [Window.defaultRouteName], which may be overridden by the code
|
||||
/// that launched the application.
|
||||
///
|
||||
/// If the route contains slashes, then it is treated as a "deep link", and
|
||||
/// before this route is pushed, the routes leading to this one are pushed
|
||||
/// also. For example, if the route was `/a/b/c`, then the app would start
|
||||
/// with the three routes `/a`, `/a/b`, and `/a/b/c` loaded, in that order.
|
||||
///
|
||||
/// If any part of this process fails to generate routes, then the
|
||||
/// [initialRoute] is ignored and [Navigator.defaultRouteName] is used instead
|
||||
/// (`/`). This can happen if the app is started with an intent that specifies
|
||||
/// a non-existent route.
|
||||
/// {@macro flutter.widgets.widgetsApp.initialRoute}
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
@ -244,19 +231,10 @@ class MaterialApp extends StatefulWidget {
|
||||
/// * [Navigator.pop], for removing a route from the stack.
|
||||
final String initialRoute;
|
||||
|
||||
/// The route generator callback used when the app is navigated to a
|
||||
/// named route.
|
||||
/// {@macro flutter.widgets.widgetsApp.onGenerateRoute}
|
||||
///
|
||||
/// This is used if [routes] does not contain the requested route.
|
||||
///
|
||||
/// If this returns null when building the routes to handle the specified
|
||||
/// [initialRoute], then all the routes are discarded and
|
||||
/// [Navigator.defaultRouteName] is used instead (`/`). See [initialRoute].
|
||||
///
|
||||
/// During normal app operation, the [onGenerateRoute] callback will only be
|
||||
/// applied to route names pushed by the application, and so should never
|
||||
/// return null.
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
/// [builder] must not be null.
|
||||
@ -265,44 +243,21 @@ class MaterialApp extends StatefulWidget {
|
||||
/// Called when [onGenerateRoute] fails to generate a route, except for the
|
||||
/// [initialRoute].
|
||||
///
|
||||
/// This callback is typically used for error handling. For example, this
|
||||
/// callback might always generate a "not found" page that describes the route
|
||||
/// that wasn't found.
|
||||
///
|
||||
/// The default implementation pushes a route that displays an ugly error
|
||||
/// message.
|
||||
/// {@macro flutter.widgets.widgetsApp.onUnknownRoute}
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
/// [builder] must not be null.
|
||||
final RouteFactory onUnknownRoute;
|
||||
|
||||
/// The list of observers for the [Navigator] created for this app.
|
||||
///
|
||||
/// This list must be replaced by a list of newly-created observers if the
|
||||
/// [navigatorKey] is changed.
|
||||
/// {@macro flutter.widgets.widgetsApp.navigatorObservers}
|
||||
///
|
||||
/// The [Navigator] is only built if routes are provided (either via [home],
|
||||
/// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not,
|
||||
/// [navigatorObservers] must be the empty list and [builder] must not be null.
|
||||
final List<NavigatorObserver> navigatorObservers;
|
||||
|
||||
/// A builder for inserting widgets above the [Navigator] but below the other
|
||||
/// widgets created by the [MaterialApp] widget, or for replacing the
|
||||
/// [Navigator] entirely.
|
||||
///
|
||||
/// For example, from the [BuildContext] passed to this method, the
|
||||
/// [Directionality], [Localizations], [DefaultTextStyle], [MediaQuery], etc,
|
||||
/// are all available. They can also be overridden in a way that impacts all
|
||||
/// the routes in the [Navigator].
|
||||
///
|
||||
/// This is rarely useful, but can be used in applications that wish to
|
||||
/// override those defaults, e.g. to force the application into right-to-left
|
||||
/// mode despite being in English, or to override the [MediaQuery] metrics
|
||||
/// (e.g. to leave a gap for advertisements shown by a plugin from OEM code).
|
||||
///
|
||||
/// The [builder] callback is passed two arguments, the [BuildContext] (as
|
||||
/// `context`) and a [Navigator] widget (as `child`).
|
||||
/// {@macro flutter.widgets.widgetsApp.builder}
|
||||
///
|
||||
/// If no routes are provided using [home], [routes], [onGenerateRoute], or
|
||||
/// [onUnknownRoute], the `child` will be null, and it is the responsibility
|
||||
@ -325,34 +280,14 @@ class MaterialApp extends StatefulWidget {
|
||||
/// [showDialog] and [showMenu], widgets such as [Tooltip], [PopupMenuButton],
|
||||
/// or [Hero], and APIs such as [Navigator.push] and [Navigator.pop], will not
|
||||
/// function.
|
||||
///
|
||||
/// For specifically overriding the [title] with a value based on the
|
||||
/// [Localizations], consider [onGenerateTitle] instead.
|
||||
final TransitionBuilder builder;
|
||||
|
||||
/// A one-line description used by the device to identify the app for the user.
|
||||
///
|
||||
/// On Android the titles appear above the task manager's app snapshots which are
|
||||
/// displayed when the user presses the "recent apps" button. Similarly, on
|
||||
/// iOS the titles appear in the App Switcher when the user double presses the
|
||||
/// home button.
|
||||
///
|
||||
/// To provide a localized title instead, use [onGenerateTitle].
|
||||
/// {@macro flutter.widgets.widgetsApp.title}
|
||||
///
|
||||
/// This value is passed unmodified to [WidgetsApp.title].
|
||||
final String title;
|
||||
|
||||
/// If non-null this callback is called to produce the app's
|
||||
/// title string, otherwise [title] is used.
|
||||
///
|
||||
/// The [onGenerateTitle] `context` parameter includes the [WidgetsApp]'s
|
||||
/// [Localizations] widget so that this callback can be used to produce a
|
||||
/// localized title.
|
||||
///
|
||||
/// This callback function must not return null.
|
||||
///
|
||||
/// The [onGenerateTitle] callback is called each time the [MaterialApp]
|
||||
/// rebuilds.
|
||||
/// {@macro flutter.widgets.widgetsApp.onGenerateTitle}
|
||||
///
|
||||
/// This value is passed unmodified to [WidgetsApp.onGenerateTitle].
|
||||
final GenerateAppTitle onGenerateTitle;
|
||||
@ -360,22 +295,13 @@ class MaterialApp extends StatefulWidget {
|
||||
/// The colors to use for the application's widgets.
|
||||
final ThemeData theme;
|
||||
|
||||
/// The primary color to use for the application in the operating system
|
||||
/// interface.
|
||||
///
|
||||
/// For example, on Android this is the color used for the application in the
|
||||
/// application switcher.
|
||||
/// {@macro flutter.widgets.widgetsApp.color}
|
||||
final Color color;
|
||||
|
||||
/// The initial locale for this app's [Localizations] widget.
|
||||
///
|
||||
/// If the `locale` is null the system's locale value is used.
|
||||
/// {@macro flutter.widgets.widgetsApp.locale}
|
||||
final Locale locale;
|
||||
|
||||
/// The delegates for this app's [Localizations] widget.
|
||||
///
|
||||
/// The delegates collectively define all of the localized resources
|
||||
/// for this application's [Localizations] widget.
|
||||
/// {@macro flutter.widgets.widgetsApp.localizationsDelegates}
|
||||
///
|
||||
/// Delegates that produce [WidgetsLocalizations] and [MaterialLocalizations]
|
||||
/// are included automatically. Apps can provide their own versions of these
|
||||
@ -433,43 +359,14 @@ class MaterialApp extends StatefulWidget {
|
||||
/// ```
|
||||
final Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates;
|
||||
|
||||
/// This callback is responsible for choosing the app's locale
|
||||
/// when the app is started, and when the user changes the
|
||||
/// device's locale.
|
||||
///
|
||||
/// The returned value becomes the locale of this app's [Localizations]
|
||||
/// widget. The callback's `locale` parameter is the device's locale when
|
||||
/// the app started, or the device locale the user selected after the app was
|
||||
/// started. The callback's `supportedLocales` parameter is just the value
|
||||
/// [supportedLocales].
|
||||
///
|
||||
/// An app could use this callback to substitute locales based on the app's
|
||||
/// intended audience. If the device's OS provides a prioritized
|
||||
/// list of locales, this callback could be used to defer to it.
|
||||
///
|
||||
/// If the callback is null then the resolved locale is:
|
||||
/// - The callback's `locale` parameter if it's equal to a supported locale.
|
||||
/// - The first supported locale with the same [Locale.languageCode] as the
|
||||
/// callback's `locale` parameter.
|
||||
/// - The first supported locale.
|
||||
/// {@macro flutter.widgets.widgetsApp.localeResolutionCallback}
|
||||
///
|
||||
/// This callback is passed along to the [WidgetsApp] built by this widget.
|
||||
final LocaleResolutionCallback localeResolutionCallback;
|
||||
|
||||
/// The list of locales that this app has been localized for.
|
||||
/// {@macro flutter.widgets.widgetsApp.supportedLocales}
|
||||
///
|
||||
/// By default only the American English locale is supported. Apps should
|
||||
/// configure this list to match the locales they support.
|
||||
///
|
||||
/// This list must not null. It's default value is just
|
||||
/// `[const Locale('en', 'US')]`. It is passed along unmodified to the
|
||||
/// [WidgetsApp] built by this widget.
|
||||
///
|
||||
/// The order of the list matters. By default, if the device's locale doesn't
|
||||
/// exactly match a locale in [supportedLocales] then the first locale in
|
||||
/// [supportedLocales] with a matching [Locale.languageCode] is used. If that
|
||||
/// fails then the first locale in [supportedLocales] is used. The default
|
||||
/// locale resolution algorithm can be overridden with [localeResolutionCallback].
|
||||
/// It is passed along unmodified to the [WidgetsApp] built by this widget.
|
||||
///
|
||||
/// The material widgets include translations for locales with the following
|
||||
/// language codes:
|
||||
@ -510,19 +407,7 @@ class MaterialApp extends StatefulWidget {
|
||||
/// reported by the framework.
|
||||
final bool showSemanticsDebugger;
|
||||
|
||||
/// Turns on a little "DEBUG" 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.
|
||||
/// {@macro flutter.widgets.widgetsApp.debugShowCheckedModeBanner}
|
||||
final bool debugShowCheckedModeBanner;
|
||||
|
||||
/// Turns on a [GridPaper] overlay that paints a baseline grid
|
||||
|
||||
@ -123,6 +123,7 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// null, [navigatorKey] must also be null.
|
||||
final GlobalKey<NavigatorState> navigatorKey;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.onGenerateRoute}
|
||||
/// The route generator callback used when the app is navigated to a
|
||||
/// named route.
|
||||
///
|
||||
@ -133,6 +134,7 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// During normal app operation, the [onGenerateRoute] callback will only be
|
||||
/// applied to route names pushed by the application, and so should never
|
||||
/// return null.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// The [Navigator] is only built if [onGenerateRoute] is not null. If
|
||||
/// [onGenerateRoute] is null, the [builder] must be non-null.
|
||||
@ -140,18 +142,21 @@ class WidgetsApp extends StatefulWidget {
|
||||
|
||||
/// Called when [onGenerateRoute] fails to generate a route.
|
||||
///
|
||||
/// {@template flutter.widgets.widgetsApp.onUnknownRoute}
|
||||
/// This callback is typically used for error handling. For example, this
|
||||
/// callback might always generate a "not found" page that describes the route
|
||||
/// that wasn't found.
|
||||
///
|
||||
/// Unknown routes can arise either from errors in the app or from external
|
||||
/// requests to push routes, such as from Android intents.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// The [Navigator] is only built if [onGenerateRoute] is not null; if it is
|
||||
/// null, [onUnknownRoute] must also be null.
|
||||
final RouteFactory onUnknownRoute;
|
||||
|
||||
/// The name of the first route to show.
|
||||
/// {@template flutter.widgets.widgetsApp.initialRoute}
|
||||
/// The name of the first route to show, if a [Navigator] is built.
|
||||
///
|
||||
/// Defaults to [Window.defaultRouteName], which may be overridden by the code
|
||||
/// that launched the application.
|
||||
@ -165,6 +170,7 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// [initialRoute] is ignored and [Navigator.defaultRouteName] is used instead
|
||||
/// (`/`). This can happen if the app is started with an intent that specifies
|
||||
/// a non-existent route.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// The [Navigator] is only built if [onGenerateRoute] is not null; if it is
|
||||
/// null, [initialRoute] must also be null.
|
||||
@ -176,16 +182,19 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// * [Navigator.pop], for removing a route from the stack.
|
||||
final String initialRoute;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.navigatorObservers}
|
||||
/// The list of observers for the [Navigator] created for this app.
|
||||
///
|
||||
/// This list must be replaced by a list of newly-created observers if the
|
||||
/// [navigatorKey] is changed.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// The [Navigator] is only built if [onGenerateRoute] is not null; if it is
|
||||
/// null, [navigatorObservers] must be left to its default value, the empty
|
||||
/// list.
|
||||
final List<NavigatorObserver> navigatorObservers;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.builder}
|
||||
/// A builder for inserting widgets above the [Navigator] but below the other
|
||||
/// widgets created by the [WidgetsApp] widget, or for replacing the
|
||||
/// [Navigator] entirely.
|
||||
@ -200,8 +209,12 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// mode despite being in English, or to override the [MediaQuery] metrics
|
||||
/// (e.g. to leave a gap for advertisements shown by a plugin from OEM code).
|
||||
///
|
||||
/// For specifically overriding the [title] with a value based on the
|
||||
/// [Localizations], consider [onGenerateTitle] instead.
|
||||
///
|
||||
/// The [builder] callback is passed two arguments, the [BuildContext] (as
|
||||
/// `context`) and a [Navigator] widget (as `child`).
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// If [onGenerateRoute] is null, the `child` will be null, and it is the
|
||||
/// responsibility of the [builder] to provide the application's routing
|
||||
@ -216,11 +229,9 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// If [builder] is null, it is as if a builder was specified that returned
|
||||
/// the `child` directly. At least one of either [onGenerateRoute] or
|
||||
/// [builder] must be non-null.
|
||||
///
|
||||
/// For specifically overriding the [title] with a value based on the
|
||||
/// [Localizations], consider [onGenerateTitle] instead.
|
||||
final TransitionBuilder builder;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.title}
|
||||
/// A one-line description used by the device to identify the app for the user.
|
||||
///
|
||||
/// On Android the titles appear above the task manager's app snapshots which are
|
||||
@ -229,8 +240,10 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// home button.
|
||||
///
|
||||
/// To provide a localized title instead, use [onGenerateTitle].
|
||||
/// {@endtemplate}
|
||||
final String title;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.onGenerateTitle}
|
||||
/// If non-null this callback function is called to produce the app's
|
||||
/// title string, otherwise [title] is used.
|
||||
///
|
||||
@ -242,29 +255,37 @@ class WidgetsApp extends StatefulWidget {
|
||||
///
|
||||
/// The [onGenerateTitle] callback is called each time the [WidgetsApp]
|
||||
/// rebuilds.
|
||||
/// {@endtemplate}
|
||||
final GenerateAppTitle onGenerateTitle;
|
||||
|
||||
/// The default text style for [Text] in the application.
|
||||
final TextStyle textStyle;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.color}
|
||||
/// The primary color to use for the application in the operating system
|
||||
/// interface.
|
||||
///
|
||||
/// For example, on Android this is the color used for the application in the
|
||||
/// application switcher.
|
||||
/// {@endtemplate}
|
||||
final Color color;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.locale}
|
||||
/// The initial locale for this app's [Localizations] widget.
|
||||
///
|
||||
/// If the 'locale' is null the system's locale value is used.
|
||||
/// {@endtemplate}
|
||||
final Locale locale;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.localizationsDelegates}
|
||||
/// The delegates for this app's [Localizations] widget.
|
||||
///
|
||||
/// The delegates collectively define all of the localized resources
|
||||
/// for this application's [Localizations] widget.
|
||||
/// {@endtemplate}
|
||||
final Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.localeResolutionCallback}
|
||||
/// This callback is responsible for choosing the app's locale
|
||||
/// when the app is started, and when the user changes the
|
||||
/// device's locale.
|
||||
@ -281,6 +302,7 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// - The first supported locale with the same [Locale.languageCode] as the
|
||||
/// callback's `locale` parameter.
|
||||
/// - The first locale in [supportedLocales].
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
@ -288,6 +310,7 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// [WidgetsApp] it creates.
|
||||
final LocaleResolutionCallback localeResolutionCallback;
|
||||
|
||||
/// {@template flutter.widgets.widgetsApp.supportedLocales}
|
||||
/// The list of locales that this app has been localized for.
|
||||
///
|
||||
/// By default only the American English locale is supported. Apps should
|
||||
@ -301,6 +324,7 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// [supportedLocales] with a matching [Locale.languageCode] is used. If that
|
||||
/// fails then the first locale in [supportedLocales] is used. The default
|
||||
/// locale resolution algorithm can be overridden with [localeResolutionCallback].
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
@ -315,7 +339,10 @@ class WidgetsApp extends StatefulWidget {
|
||||
final Iterable<Locale> supportedLocales;
|
||||
|
||||
/// Turns on a performance overlay.
|
||||
/// https://flutter.io/debugging/#performanceoverlay
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * <https://flutter.io/debugging/#performanceoverlay>
|
||||
final bool showPerformanceOverlay;
|
||||
|
||||
/// Checkerboards raster cache images.
|
||||
@ -347,7 +374,8 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// material package.
|
||||
final InspectorSelectButtonBuilder inspectorSelectButtonBuilder;
|
||||
|
||||
/// Turns on a "DEBUG" little banner in checked mode to indicate
|
||||
/// {@template flutter.widgets.widgetsApp.debugShowCheckedModeBanner}
|
||||
/// Turns on a little "DEBUG" 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.
|
||||
@ -355,11 +383,12 @@ class WidgetsApp extends StatefulWidget {
|
||||
/// 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 avoid people complaining that your
|
||||
/// 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.
|
||||
/// {@endtemplate}
|
||||
final bool debugShowCheckedModeBanner;
|
||||
|
||||
/// If true, forces the performance overlay to be visible in all instances.
|
||||
|
||||
@ -16,19 +16,11 @@ int count = 0;
|
||||
void main() {
|
||||
testWidgets('Middle still in center with asymmetrical actions', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoNavigationBar(
|
||||
leading: const CupertinoButton(child: const Text('Something'), onPressed: null,),
|
||||
middle: const Text('Title'),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoNavigationBar(
|
||||
leading: const CupertinoButton(child: const Text('Something'), onPressed: null,),
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -38,19 +30,11 @@ void main() {
|
||||
|
||||
testWidgets('Opaque background does not add blur effects', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
backgroundColor: const Color(0xFFE5E5E5),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
backgroundColor: const Color(0xFFE5E5E5),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.byType(BackdropFilter), findsNothing);
|
||||
@ -58,18 +42,10 @@ void main() {
|
||||
|
||||
testWidgets('Non-opaque background adds blur effects', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.byType(BackdropFilter), findsOneWidget);
|
||||
@ -78,21 +54,13 @@ void main() {
|
||||
testWidgets('Verify styles of each slot', (WidgetTester tester) async {
|
||||
count = 0x000000;
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoNavigationBar(
|
||||
leading: const _ExpectStyles(color: const Color(0xFF001122), index: 0x000001),
|
||||
middle: const _ExpectStyles(color: const Color(0xFF000000), letterSpacing: -0.08, index: 0x000100),
|
||||
trailing: const _ExpectStyles(color: const Color(0xFF001122), index: 0x010000),
|
||||
actionsForegroundColor: const Color(0xFF001122),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoNavigationBar(
|
||||
leading: const _ExpectStyles(color: const Color(0xFF001122), index: 0x000001),
|
||||
middle: const _ExpectStyles(color: const Color(0xFF000000), letterSpacing: -0.08, index: 0x000100),
|
||||
trailing: const _ExpectStyles(color: const Color(0xFF001122), index: 0x010000),
|
||||
actionsForegroundColor: const Color(0xFF001122),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(count, 0x010101);
|
||||
@ -100,21 +68,13 @@ void main() {
|
||||
|
||||
testWidgets('No slivers with no large titles', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
child: const Center(),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
child: const Center(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -128,43 +88,35 @@ void main() {
|
||||
final Key trailingKey = new GlobalKey();
|
||||
final Key titleKey = new GlobalKey();
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10.0,
|
||||
left: 20.0,
|
||||
bottom: 30.0,
|
||||
right: 40.0,
|
||||
new CupertinoApp(
|
||||
home: new MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10.0,
|
||||
left: 20.0,
|
||||
bottom: 30.0,
|
||||
right: 40.0,
|
||||
),
|
||||
),
|
||||
child: new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
controller: scrollController,
|
||||
slivers: <Widget>[
|
||||
new CupertinoSliverNavigationBar(
|
||||
leading: new Placeholder(key: leadingKey),
|
||||
middle: new Placeholder(key: middleKey),
|
||||
largeTitle: new Text('Large Title', key: titleKey),
|
||||
trailing: new Placeholder(key: trailingKey),
|
||||
),
|
||||
new SliverToBoxAdapter(
|
||||
child: new Container(
|
||||
height: 1200.0,
|
||||
),
|
||||
),
|
||||
child: new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
controller: scrollController,
|
||||
slivers: <Widget>[
|
||||
new CupertinoSliverNavigationBar(
|
||||
leading: new Placeholder(key: leadingKey),
|
||||
middle: new Placeholder(key: middleKey),
|
||||
largeTitle: new Text('Large Title', key: titleKey),
|
||||
trailing: new Placeholder(key: trailingKey),
|
||||
),
|
||||
new SliverToBoxAdapter(
|
||||
child: new Container(
|
||||
height: 1200.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -180,30 +132,22 @@ void main() {
|
||||
testWidgets('Large title nav bar scrolls', (WidgetTester tester) async {
|
||||
final ScrollController scrollController = new ScrollController();
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
controller: scrollController,
|
||||
slivers: <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Title'),
|
||||
),
|
||||
new SliverToBoxAdapter(
|
||||
child: new Container(
|
||||
height: 1200.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
new CupertinoApp(
|
||||
home: new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
controller: scrollController,
|
||||
slivers: <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Title'),
|
||||
),
|
||||
new SliverToBoxAdapter(
|
||||
child: new Container(
|
||||
height: 1200.0,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -268,31 +212,23 @@ void main() {
|
||||
testWidgets('Small title can be overridden', (WidgetTester tester) async {
|
||||
final ScrollController scrollController = new ScrollController();
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
controller: scrollController,
|
||||
slivers: <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
middle: const Text('Different title'),
|
||||
largeTitle: const Text('Title'),
|
||||
),
|
||||
new SliverToBoxAdapter(
|
||||
child: new Container(
|
||||
height: 1200.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
new CupertinoApp(
|
||||
home: new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
controller: scrollController,
|
||||
slivers: <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
middle: const Text('Different title'),
|
||||
largeTitle: const Text('Title'),
|
||||
),
|
||||
new SliverToBoxAdapter(
|
||||
child: new Container(
|
||||
height: 1200.0,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -339,18 +275,10 @@ void main() {
|
||||
|
||||
testWidgets('Auto back/close button', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoNavigationBar(
|
||||
middle: const Text('Home page'),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoNavigationBar(
|
||||
middle: const Text('Home page'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -403,18 +331,10 @@ void main() {
|
||||
|
||||
testWidgets('Border should be displayed by default', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -433,24 +353,16 @@ void main() {
|
||||
|
||||
testWidgets('Overrides border color', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
border: const Border(
|
||||
bottom: const BorderSide(
|
||||
color: const Color(0xFFAABBCC),
|
||||
width: 0.0,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
border: const Border(
|
||||
bottom: const BorderSide(
|
||||
color: const Color(0xFFAABBCC),
|
||||
width: 0.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -470,19 +382,11 @@ void main() {
|
||||
|
||||
testWidgets('Border should not be displayed when null', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
border: null,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
border: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -500,24 +404,16 @@ void main() {
|
||||
'Border is displayed by default in sliver nav bar',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: const <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Large Title'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: const <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Large Title'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -538,25 +434,17 @@ void main() {
|
||||
'Border is not displayed when null in sliver nav bar',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: const <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Large Title'),
|
||||
border: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: const <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Large Title'),
|
||||
border: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -573,25 +461,17 @@ void main() {
|
||||
testWidgets('CupertinoSliverNavigationBar has semantics', (WidgetTester tester) async {
|
||||
final SemanticsTester semantics = new SemanticsTester(tester);
|
||||
|
||||
await tester.pumpWidget(new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: const <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Large Title'),
|
||||
border: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
await tester.pumpWidget(new CupertinoApp(
|
||||
home: new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: const <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Large Title'),
|
||||
border: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
expect(semantics.nodesWith(
|
||||
@ -606,21 +486,13 @@ void main() {
|
||||
testWidgets('CupertinoNavigationBar has semantics', (WidgetTester tester) async {
|
||||
final SemanticsTester semantics = new SemanticsTester(tester);
|
||||
|
||||
await tester.pumpWidget(new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Fixed Title'),
|
||||
),
|
||||
child: new Container(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
await tester.pumpWidget(new CupertinoApp(
|
||||
home: new CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Fixed Title'),
|
||||
),
|
||||
child: new Container(),
|
||||
),
|
||||
));
|
||||
|
||||
expect(semantics.nodesWith(
|
||||
@ -636,30 +508,22 @@ void main() {
|
||||
'Border can be overridden in sliver nav bar',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: const <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Large Title'),
|
||||
border: const Border(
|
||||
bottom: const BorderSide(
|
||||
color: const Color(0xFFAABBCC),
|
||||
width: 0.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
new CupertinoApp(
|
||||
home: new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: const <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Large Title'),
|
||||
border: const Border(
|
||||
bottom: const BorderSide(
|
||||
color: const Color(0xFFAABBCC),
|
||||
width: 0.0,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -684,23 +548,15 @@ void main() {
|
||||
'Standard title golden',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const RepaintBoundary(
|
||||
child: const CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Bling bling'),
|
||||
),
|
||||
child: const Center(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const RepaintBoundary(
|
||||
child: const CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Bling bling'),
|
||||
),
|
||||
child: const Center(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -718,29 +574,23 @@ void main() {
|
||||
'Large title golden',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Bling bling'),
|
||||
),
|
||||
new SliverToBoxAdapter(
|
||||
child: new Container(
|
||||
height: 1200.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
new CupertinoApp(
|
||||
home: new RepaintBoundary(
|
||||
child: new CupertinoPageScaffold(
|
||||
child: new CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('Bling bling'),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new SliverToBoxAdapter(
|
||||
child: new Container(
|
||||
height: 1200.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@ -8,8 +8,7 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
void main() {
|
||||
testWidgets('test iOS page transition (LTR)', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
new CupertinoApp(
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
@ -76,11 +75,10 @@ void main() {
|
||||
|
||||
testWidgets('test iOS page transition (RTL)', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
new CupertinoApp(
|
||||
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
|
||||
const RtlOverrideWidgetsDelegate(),
|
||||
],
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
@ -148,16 +146,8 @@ void main() {
|
||||
|
||||
testWidgets('test iOS fullscreen dialog transition', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const Center(child: const Text('Page 1'));
|
||||
}
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const Center(child: const Text('Page 1')),
|
||||
),
|
||||
);
|
||||
|
||||
@ -216,8 +206,7 @@ void main() {
|
||||
|
||||
testWidgets('test only edge swipes work (LTR)', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
new CupertinoApp(
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
@ -278,11 +267,10 @@ void main() {
|
||||
|
||||
testWidgets('test only edge swipes work (RTL)', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
new CupertinoApp(
|
||||
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
|
||||
const RtlOverrideWidgetsDelegate(),
|
||||
],
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
|
||||
@ -11,22 +11,14 @@ import '../painting/mocks_for_image_cache.dart';
|
||||
void main() {
|
||||
testWidgets('Contents are behind translucent bar', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoPageScaffold(
|
||||
// Default nav bar is translucent.
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
child: const Center(),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoPageScaffold(
|
||||
// Default nav bar is translucent.
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
child: const Center(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -37,41 +29,33 @@ void main() {
|
||||
const Center page1Center = const Center();
|
||||
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabScaffold(
|
||||
tabBar: new CupertinoTabBar(
|
||||
backgroundColor: CupertinoColors.white,
|
||||
items: const <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
],
|
||||
),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return index == 0
|
||||
? const CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
backgroundColor: CupertinoColors.white,
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
child: page1Center,
|
||||
)
|
||||
: new Stack();
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabScaffold(
|
||||
tabBar: new CupertinoTabBar(
|
||||
backgroundColor: CupertinoColors.white,
|
||||
items: const <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
],
|
||||
),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return index == 0
|
||||
? const CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
backgroundColor: CupertinoColors.white,
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
child: page1Center,
|
||||
)
|
||||
: new Stack();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -82,48 +66,40 @@ void main() {
|
||||
final Container content = new Container(height: 600.0, width: 600.0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20.0),
|
||||
new CupertinoApp(
|
||||
home: new MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20.0),
|
||||
),
|
||||
child: new CupertinoTabScaffold(
|
||||
tabBar: new CupertinoTabBar(
|
||||
items: const <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
child: new CupertinoTabScaffold(
|
||||
tabBar: new CupertinoTabBar(
|
||||
items: const <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
],
|
||||
),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return index == 0
|
||||
? new CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
child: new ListView(
|
||||
children: <Widget>[
|
||||
content,
|
||||
],
|
||||
),
|
||||
)
|
||||
: new Stack();
|
||||
}
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
],
|
||||
),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return index == 0
|
||||
? new CupertinoPageScaffold(
|
||||
navigationBar: const CupertinoNavigationBar(
|
||||
middle: const Text('Title'),
|
||||
),
|
||||
child: new ListView(
|
||||
children: <Widget>[
|
||||
content,
|
||||
],
|
||||
),
|
||||
)
|
||||
: new Stack();
|
||||
}
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -132,6 +108,8 @@ void main() {
|
||||
|
||||
// Overscroll to the bottom.
|
||||
await tester.drag(find.byWidget(content), const Offset(0.0, -400.0));
|
||||
// Let it bounce back.
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
|
||||
// List content automatically padded by tab bar and bottom media query padding.
|
||||
@ -142,68 +120,60 @@ void main() {
|
||||
// A full on iOS information architecture app with 2 tabs, and 2 pages
|
||||
// in each with independent navigation states.
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabScaffold(
|
||||
tabBar: new CupertinoTabBar(
|
||||
items: const <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
],
|
||||
),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
// For 1-indexed readability.
|
||||
++index;
|
||||
return new CupertinoTabView(
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
navigationBar: new CupertinoNavigationBar(
|
||||
middle: new Text('Page 1 of tab $index'),
|
||||
),
|
||||
child: new Center(
|
||||
child: new CupertinoButton(
|
||||
child: const Text('Next'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
new CupertinoPageRoute<void>(
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
navigationBar: new CupertinoNavigationBar(
|
||||
middle: new Text('Page 2 of tab $index'),
|
||||
),
|
||||
child: new Center(
|
||||
child: new CupertinoButton(
|
||||
child: const Text('Back'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabScaffold(
|
||||
tabBar: new CupertinoTabBar(
|
||||
items: const <BottomNavigationBarItem>[
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 1'),
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: const ImageIcon(const TestImageProvider(24, 24)),
|
||||
title: const Text('Tab 2'),
|
||||
),
|
||||
],
|
||||
),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
// For 1-indexed readability.
|
||||
++index;
|
||||
return new CupertinoTabView(
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
navigationBar: new CupertinoNavigationBar(
|
||||
middle: new Text('Page 1 of tab $index'),
|
||||
),
|
||||
child: new Center(
|
||||
child: new CupertinoButton(
|
||||
child: const Text('Next'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
new CupertinoPageRoute<void>(
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoPageScaffold(
|
||||
navigationBar: new CupertinoNavigationBar(
|
||||
middle: new Text('Page 2 of tab $index'),
|
||||
),
|
||||
child: new Center(
|
||||
child: new CupertinoButton(
|
||||
child: const Text('Back'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -257,18 +227,10 @@ void main() {
|
||||
|
||||
testWidgets('Decorated with white background by default', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoPageScaffold(
|
||||
child: const Center(),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoPageScaffold(
|
||||
child: const Center(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -281,19 +243,11 @@ void main() {
|
||||
|
||||
testWidgets('Overrides background color', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const CupertinoPageScaffold(
|
||||
child: const Center(),
|
||||
backgroundColor: const Color(0xFF010203),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: const CupertinoPageScaffold(
|
||||
child: const Center(),
|
||||
backgroundColor: const Color(0xFF010203),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@ -20,26 +20,18 @@ void main() {
|
||||
final List<int> tabsPainted = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new CustomPaint(
|
||||
child: new Text('Page ${index + 1}'),
|
||||
painter: new TestCallbackPainter(
|
||||
onPaint: () { tabsPainted.add(index); }
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new CustomPaint(
|
||||
child: new Text('Page ${index + 1}'),
|
||||
painter: new TestCallbackPainter(
|
||||
onPaint: () { tabsPainted.add(index); }
|
||||
)
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -82,22 +74,14 @@ void main() {
|
||||
final List<int> tabsBuilt = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
tabsBuilt.add(index);
|
||||
return new Text('Page ${index + 1}');
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
tabsBuilt.add(index);
|
||||
return new Text('Page ${index + 1}');
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -126,26 +110,18 @@ void main() {
|
||||
final List<FocusNode> focusNodes = <FocusNode>[new FocusNode(), new FocusNode()];
|
||||
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new Material(
|
||||
child: new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new TextField(
|
||||
focusNode: focusNodes[index],
|
||||
autofocus: true,
|
||||
);
|
||||
},
|
||||
),
|
||||
new CupertinoApp(
|
||||
home: new Material(
|
||||
child: new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new TextField(
|
||||
focusNode: focusNodes[index],
|
||||
autofocus: true,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -170,38 +146,30 @@ void main() {
|
||||
];
|
||||
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new Material(
|
||||
child: new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new Column(
|
||||
children: <Widget>[
|
||||
new TextField(
|
||||
focusNode: focusNodes[index * 2],
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'TextField 1',
|
||||
),
|
||||
),
|
||||
new TextField(
|
||||
focusNode: focusNodes[index * 2 + 1],
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'TextField 2',
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
new CupertinoApp(
|
||||
home: new Material(
|
||||
child: new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new Column(
|
||||
children: <Widget>[
|
||||
new TextField(
|
||||
focusNode: focusNodes[index * 2],
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'TextField 1',
|
||||
),
|
||||
),
|
||||
new TextField(
|
||||
focusNode: focusNodes[index * 2 + 1],
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'TextField 2',
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -242,42 +210,36 @@ void main() {
|
||||
final List<int> tabsPainted = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
builder: (BuildContext context, Widget child) {
|
||||
return new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new CustomPaint(
|
||||
child: new Text('Page ${index + 1}'),
|
||||
painter: new TestCallbackPainter(
|
||||
onPaint: () { tabsPainted.add(index); }
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new CustomPaint(
|
||||
child: new Text('Page ${index + 1}'),
|
||||
painter: new TestCallbackPainter(
|
||||
onPaint: () { tabsPainted.add(index); }
|
||||
)
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(tabsPainted, <int>[0]);
|
||||
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
builder: (BuildContext context, Widget child) {
|
||||
return new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(selectedTab: 1), // Programmatically change the tab now.
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new CustomPaint(
|
||||
child: new Text('Page ${index + 1}'),
|
||||
painter: new TestCallbackPainter(
|
||||
onPaint: () { tabsPainted.add(index); }
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(selectedTab: 1), // Programmatically change the tab now.
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new CustomPaint(
|
||||
child: new Text('Page ${index + 1}'),
|
||||
painter: new TestCallbackPainter(
|
||||
onPaint: () { tabsPainted.add(index); }
|
||||
)
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@ -8,18 +8,10 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
void main() {
|
||||
testWidgets('Use home', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabView(
|
||||
builder: (BuildContext context) => const Text('home'),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabView(
|
||||
builder: (BuildContext context) => const Text('home'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -28,20 +20,12 @@ void main() {
|
||||
|
||||
testWidgets('Use routes', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabView(
|
||||
routes: <String, WidgetBuilder>{
|
||||
'/': (BuildContext context) => const Text('first route'),
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabView(
|
||||
routes: <String, WidgetBuilder>{
|
||||
'/': (BuildContext context) => const Text('first route'),
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -50,28 +34,20 @@ void main() {
|
||||
|
||||
testWidgets('Use home and named routes', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabView(
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoButton(
|
||||
child: const Text('go to second page'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed('/2');
|
||||
},
|
||||
);
|
||||
},
|
||||
routes: <String, WidgetBuilder>{
|
||||
'/2': (BuildContext context) => const Text('second named route'),
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabView(
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoButton(
|
||||
child: const Text('go to second page'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed('/2');
|
||||
},
|
||||
);
|
||||
},
|
||||
routes: <String, WidgetBuilder>{
|
||||
'/2': (BuildContext context) => const Text('second named route'),
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -84,27 +60,19 @@ void main() {
|
||||
|
||||
testWidgets('Use onGenerateRoute', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabView(
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
if (settings.name == Navigator.defaultRouteName) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const Text('generated home');
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabView(
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
if (settings.name == Navigator.defaultRouteName) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return const Text('generated home');
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -114,20 +82,12 @@ void main() {
|
||||
testWidgets('Use onUnknownRoute', (WidgetTester tester) async {
|
||||
String unknownForRouteCalled;
|
||||
await tester.pumpWidget(
|
||||
new WidgetsApp(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabView(
|
||||
onUnknownRoute: (RouteSettings settings) {
|
||||
unknownForRouteCalled = settings.name;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
new CupertinoApp(
|
||||
home: new CupertinoTabView(
|
||||
onUnknownRoute: (RouteSettings settings) {
|
||||
unknownForRouteCalled = settings.name;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user