Merge NNBD branch into master (#270)

This commit is contained in:
Michael Goderbauer
2021-01-27 12:55:35 -08:00
committed by GitHub
parent 1c7d23bdbe
commit f3e92fded0
23 changed files with 449 additions and 732 deletions

View File

@ -7,6 +7,9 @@ task:
upgrade_script:
- flutter channel master
- flutter upgrade
# TODO(goderbauer): Remove next two lines when https://github.com/flutter/flutter/issues/74772 is resolved.
- rm -rf /home/cirrus/sdks/flutter/bin/cache
- flutter doctor
- git fetch origin master
activate_script: pub global activate flutter_plugin_tools
matrix:

View File

@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
## [2.0.0-nullsafety.0] - November 16, 2020
* Migrates to null safety.
## [1.1.2] - July 28, 2020
* Fixes for upcoming changes to the flutter framework.

View File

@ -50,7 +50,7 @@ class _OpenContainerTransformDemoState
extends State<OpenContainerTransformDemo> {
ContainerTransitionType _transitionType = ContainerTransitionType.fade;
void _showMarkedAsDoneSnackbar(bool isMarkedAsDone) {
void _showMarkedAsDoneSnackbar(bool? isMarkedAsDone) {
if (isMarkedAsDone ?? false)
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Marked as done!'),
@ -271,14 +271,14 @@ class _OpenContainerTransformDemoState
class _OpenContainerWrapper extends StatelessWidget {
const _OpenContainerWrapper({
this.closedBuilder,
this.transitionType,
this.onClosed,
required this.closedBuilder,
required this.transitionType,
required this.onClosed,
});
final OpenContainerBuilder closedBuilder;
final CloseContainerBuilder closedBuilder;
final ContainerTransitionType transitionType;
final ClosedCallback<bool> onClosed;
final ClosedCallback<bool?> onClosed;
@override
Widget build(BuildContext context) {
@ -295,7 +295,7 @@ class _OpenContainerWrapper extends StatelessWidget {
}
class _ExampleCard extends StatelessWidget {
const _ExampleCard({this.openContainer});
const _ExampleCard({required this.openContainer});
final VoidCallback openContainer;
@ -333,7 +333,7 @@ class _ExampleCard extends StatelessWidget {
'adipiscing elit, sed do eiusmod tempor.',
style: Theme.of(context)
.textTheme
.bodyText2
.bodyText2!
.copyWith(color: Colors.black54),
),
),
@ -345,8 +345,8 @@ class _ExampleCard extends StatelessWidget {
class _SmallerCard extends StatelessWidget {
const _SmallerCard({
this.openContainer,
this.subtitle,
required this.openContainer,
required this.subtitle,
});
final VoidCallback openContainer;
@ -397,7 +397,7 @@ class _SmallerCard extends StatelessWidget {
}
class _ExampleSingleTile extends StatelessWidget {
const _ExampleSingleTile({this.openContainer});
const _ExampleSingleTile({required this.openContainer});
final VoidCallback openContainer;
@ -454,10 +454,10 @@ class _InkWellOverlay extends StatelessWidget {
this.child,
});
final VoidCallback openContainer;
final double width;
final double height;
final Widget child;
final VoidCallback? openContainer;
final double? width;
final double? height;
final Widget? child;
@override
Widget build(BuildContext context) {
@ -510,7 +510,7 @@ class _DetailsPage extends StatelessWidget {
children: <Widget>[
Text(
'Title',
style: Theme.of(context).textTheme.headline5.copyWith(
style: Theme.of(context).textTheme.headline5!.copyWith(
color: Colors.black54,
fontSize: 30.0,
),
@ -518,7 +518,7 @@ class _DetailsPage extends StatelessWidget {
const SizedBox(height: 10),
Text(
_loremIpsumParagraph,
style: Theme.of(context).textTheme.bodyText2.copyWith(
style: Theme.of(context).textTheme.bodyText2!.copyWith(
color: Colors.black54,
height: 1.5,
fontSize: 16.0,

View File

@ -14,7 +14,7 @@ class FadeScaleTransitionDemo extends StatefulWidget {
class _FadeScaleTransitionDemoState extends State<FadeScaleTransitionDemo>
with SingleTickerProviderStateMixin {
AnimationController _controller;
late AnimationController _controller;
@override
void initState() {
@ -48,8 +48,6 @@ class _FadeScaleTransitionDemoState extends State<FadeScaleTransitionDemo>
case AnimationStatus.dismissed:
return false;
}
assert(false);
return null;
}
@override
@ -58,7 +56,7 @@ class _FadeScaleTransitionDemoState extends State<FadeScaleTransitionDemo>
appBar: AppBar(title: const Text('Fade')),
floatingActionButton: AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget child) {
builder: (BuildContext context, Widget? child) {
return FadeScaleTransition(
animation: _controller,
child: child,

View File

@ -126,11 +126,11 @@ class _TransitionsHomePageState extends State<_TransitionsHomePage> {
class _TransitionListTile extends StatelessWidget {
const _TransitionListTile({
this.onTap,
this.title,
this.subtitle,
required this.title,
required this.subtitle,
});
final GestureTapCallback onTap;
final GestureTapCallback? onTap;
final String title;
final String subtitle;

View File

@ -14,11 +14,11 @@ class SharedAxisTransitionDemo extends StatefulWidget {
}
class _SharedAxisTransitionDemoState extends State<SharedAxisTransitionDemo> {
SharedAxisTransitionType _transitionType =
SharedAxisTransitionType? _transitionType =
SharedAxisTransitionType.horizontal;
bool _isLoggedIn = false;
void _updateTransitionType(SharedAxisTransitionType newType) {
void _updateTransitionType(SharedAxisTransitionType? newType) {
setState(() {
_transitionType = newType;
});
@ -51,7 +51,7 @@ class _SharedAxisTransitionDemoState extends State<SharedAxisTransitionDemo> {
child: child,
animation: animation,
secondaryAnimation: secondaryAnimation,
transitionType: _transitionType,
transitionType: _transitionType!,
);
},
child: _isLoggedIn ? _CoursePage() : _SignInPage(),
@ -80,7 +80,7 @@ class _SharedAxisTransitionDemoState extends State<SharedAxisTransitionDemo> {
Radio<SharedAxisTransitionType>(
value: SharedAxisTransitionType.horizontal,
groupValue: _transitionType,
onChanged: (SharedAxisTransitionType newValue) {
onChanged: (SharedAxisTransitionType? newValue) {
_updateTransitionType(newValue);
},
),
@ -88,7 +88,7 @@ class _SharedAxisTransitionDemoState extends State<SharedAxisTransitionDemo> {
Radio<SharedAxisTransitionType>(
value: SharedAxisTransitionType.vertical,
groupValue: _transitionType,
onChanged: (SharedAxisTransitionType newValue) {
onChanged: (SharedAxisTransitionType? newValue) {
_updateTransitionType(newValue);
},
),
@ -96,7 +96,7 @@ class _SharedAxisTransitionDemoState extends State<SharedAxisTransitionDemo> {
Radio<SharedAxisTransitionType>(
value: SharedAxisTransitionType.scaled,
groupValue: _transitionType,
onChanged: (SharedAxisTransitionType newValue) {
onChanged: (SharedAxisTransitionType? newValue) {
_updateTransitionType(newValue);
},
),
@ -146,7 +146,7 @@ class _CoursePage extends StatelessWidget {
class _CourseSwitch extends StatefulWidget {
const _CourseSwitch({
this.course,
required this.course,
});
final String course;

View File

@ -6,7 +6,7 @@ publish_to: none
version: 0.0.1
environment:
sdk: ">=2.3.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
dependencies:
animations:

View File

@ -1,203 +0,0 @@
// Copyright 2020 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(shihaohong): Remove DualTransitionBuilder once flutter/flutter's `stable`
// branch contains DualTransitionBuilder.
import 'package:flutter/widgets.dart';
/// Builder callback used by [DualTransitionBuilder].
///
/// The builder is expected to return a transition powered by the provided
/// `animation` and wrapping the provided `child`.
///
/// The `animation` provided to the builder always runs forward from 0.0 to 1.0.
typedef TransitionBuilder = Widget Function(
BuildContext context,
Animation<double> animation,
Widget child,
);
/// A transition builder that animates its [child] based on the
/// [AnimationStatus] of the provided [animation].
///
/// This widget can be used to specify different enter and exit transitions for
/// a [child].
///
/// While the [animation] runs forward, the [child] is animated according to
/// [forwardBuilder] and while the [animation] is running in reverse, it is
/// animated according to [reverseBuilder].
///
/// Using this builder allows the widget tree to maintain its shape by nesting
/// the enter and exit transitions. This ensures that no state information of
/// any descendant widget is lost when the transition starts or completes.
class DualTransitionBuilder extends StatefulWidget {
/// Creates a [DualTransitionBuilder].
///
/// The [animation], [forwardBuilder], and [reverseBuilder] arguments are
/// required and must not be null.
const DualTransitionBuilder({
Key key,
@required this.animation,
@required this.forwardBuilder,
@required this.reverseBuilder,
this.child,
}) : assert(animation != null),
assert(forwardBuilder != null),
assert(reverseBuilder != null),
super(key: key);
/// The animation that drives the [child]'s transition.
///
/// When this animation runs forward, the [child] transitions as specified by
/// [forwardBuilder]. When it runs in reverse, the child transitions according
/// to [reverseBuilder].
final Animation<double> animation;
/// A builder for the transition that makes [child] appear on screen.
///
/// The [child] should be fully visible when the provided `animation` reaches
/// 1.0.
///
/// The `animation` provided to this builder is running forward from 0.0 to
/// 1.0 when [animation] runs _forward_. When [animation] runs in reverse,
/// the given `animation` is set to [kAlwaysCompleteAnimation].
///
/// See also:
///
/// * [reverseBuilder], which builds the transition for making the [child]
/// disappear from the screen.
final TransitionBuilder forwardBuilder;
/// A builder for a transition that makes [child] disappear from the screen.
///
/// The [child] should be fully invisible when the provided `animation`
/// reaches 1.0.
///
/// The `animation` provided to this builder is running forward from 0.0 to
/// 1.0 when [animation] runs in _reverse_. When [animation] runs forward,
/// the given `animation` is set to [kAlwaysDismissedAnimation].
///
/// See also:
///
/// * [forwardBuilder], which builds the transition for making the [child]
/// appear on screen.
final TransitionBuilder reverseBuilder;
/// The widget below this [DualTransitionBuilder] in the tree.
///
/// This child widget will be wrapped by the transitions built by
/// [forwardBuilder] and [reverseBuilder].
final Widget child;
@override
State<DualTransitionBuilder> createState() => _DualTransitionBuilderState();
}
class _DualTransitionBuilderState extends State<DualTransitionBuilder> {
AnimationStatus _effectiveAnimationStatus;
final ProxyAnimation _forwardAnimation = ProxyAnimation();
final ProxyAnimation _reverseAnimation = ProxyAnimation();
@override
void initState() {
super.initState();
_effectiveAnimationStatus = widget.animation.status;
widget.animation.addStatusListener(_animationListener);
_updateAnimations();
}
void _animationListener(AnimationStatus animationStatus) {
final AnimationStatus oldEffective = _effectiveAnimationStatus;
_effectiveAnimationStatus = _calculateEffectiveAnimationStatus(
lastEffective: _effectiveAnimationStatus,
current: animationStatus,
);
if (oldEffective != _effectiveAnimationStatus) {
_updateAnimations();
}
}
@override
void didUpdateWidget(DualTransitionBuilder oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.animation != widget.animation) {
oldWidget.animation.removeStatusListener(_animationListener);
widget.animation.addStatusListener(_animationListener);
_animationListener(widget.animation.status);
}
}
// When a transition is interrupted midway we just want to play the ongoing
// animation in reverse. Switching to the actual reverse transition would
// yield a disjoint experience since the forward and reverse transitions are
// very different.
AnimationStatus _calculateEffectiveAnimationStatus({
@required AnimationStatus lastEffective,
@required AnimationStatus current,
}) {
assert(current != null);
assert(lastEffective != null);
switch (current) {
case AnimationStatus.dismissed:
case AnimationStatus.completed:
return current;
case AnimationStatus.forward:
switch (lastEffective) {
case AnimationStatus.dismissed:
case AnimationStatus.completed:
case AnimationStatus.forward:
return current;
case AnimationStatus.reverse:
return lastEffective;
}
break;
case AnimationStatus.reverse:
switch (lastEffective) {
case AnimationStatus.dismissed:
case AnimationStatus.completed:
case AnimationStatus.reverse:
return current;
case AnimationStatus.forward:
return lastEffective;
}
break;
}
return null; // unreachable
}
void _updateAnimations() {
switch (_effectiveAnimationStatus) {
case AnimationStatus.dismissed:
case AnimationStatus.forward:
_forwardAnimation.parent = widget.animation;
_reverseAnimation.parent = kAlwaysDismissedAnimation;
break;
case AnimationStatus.reverse:
case AnimationStatus.completed:
_forwardAnimation.parent = kAlwaysCompleteAnimation;
_reverseAnimation.parent = ReverseAnimation(widget.animation);
break;
}
}
@override
void dispose() {
widget.animation.removeStatusListener(_animationListener);
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.forwardBuilder(
context,
_forwardAnimation,
widget.reverseBuilder(
context,
_reverseAnimation,
widget.child,
),
);
}
}

View File

@ -2,14 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart'
hide decelerateEasing; // ignore: undefined_hidden_name
// TODO(goderbauer): Remove implementation import when material properly exports the file.
import 'package:flutter/src/material/curves.dart'; // ignore: implementation_imports
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
// TODO(shihaohong): Remove DualTransitionBuilder once flutter/flutter's `stable`
// branch contains DualTransitionBuilder.
import 'dual_transition_builder.dart' as dual_transition_builder;
import 'modal.dart';
/// The modal transition configuration for a Material fade transition.
@ -121,11 +116,10 @@ class FadeScaleTransition extends StatelessWidget {
/// [animation] is typically an [AnimationController] that drives the transition
/// animation. [animation] cannot be null.
const FadeScaleTransition({
Key key,
@required this.animation,
Key? key,
required this.animation,
this.child,
}) : assert(animation != null),
super(key: key);
}) : super(key: key);
/// The animation that drives the [child]'s entrance and exit.
///
@ -139,7 +133,7 @@ class FadeScaleTransition extends StatelessWidget {
///
/// This widget will transition in and out as driven by [animation] and
/// [secondaryAnimation].
final Widget child;
final Widget? child;
static final Animatable<double> _fadeInTransition = CurveTween(
curve: const Interval(0.0, 0.3),
@ -155,12 +149,12 @@ class FadeScaleTransition extends StatelessWidget {
@override
Widget build(BuildContext context) {
return dual_transition_builder.DualTransitionBuilder(
return DualTransitionBuilder(
animation: animation,
forwardBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return FadeTransition(
opacity: _fadeInTransition.animate(animation),
@ -173,7 +167,7 @@ class FadeScaleTransition extends StatelessWidget {
reverseBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return FadeTransition(
opacity: _fadeOutTransition.animate(animation),

View File

@ -3,10 +3,7 @@
// found in the LICENSE file.
import 'package:flutter/material.dart';
// TODO(shihaohong): Remove DualTransitionBuilder once flutter/flutter's `stable`
// branch contains DualTransitionBuilder.
import 'dual_transition_builder.dart' as dual_transition_builder;
import 'package:flutter/widgets.dart';
/// Used by [PageTransitionsTheme] to define a page route transition animation
/// in which the outgoing page fades out, then the incoming page fades in and
@ -69,12 +66,12 @@ class FadeThroughPageTransitionsBuilder extends PageTransitionsBuilder {
/// The color to use for the background color during the transition.
///
/// This defaults to the [Theme]'s [ThemeData.canvasColor].
final Color fillColor;
final Color? fillColor;
@override
Widget buildTransitions<T>(
PageRoute<T> route,
BuildContext context,
PageRoute<T>? route,
BuildContext? context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
@ -166,12 +163,11 @@ class FadeThroughTransition extends StatelessWidget {
/// The [animation] and [secondaryAnimation] argument are required and must
/// not be null.
const FadeThroughTransition({
@required this.animation,
@required this.secondaryAnimation,
required this.animation,
required this.secondaryAnimation,
this.fillColor,
this.child,
}) : assert(animation != null),
assert(secondaryAnimation != null);
});
/// The animation that drives the [child]'s entrance and exit.
///
@ -193,13 +189,13 @@ class FadeThroughTransition extends StatelessWidget {
/// The color to use for the background color during the transition.
///
/// This defaults to the [Theme]'s [ThemeData.canvasColor].
final Color fillColor;
final Color? fillColor;
/// The widget below this widget in the tree.
///
/// This widget will transition in and out as driven by [animation] and
/// [secondaryAnimation].
final Widget child;
final Widget? child;
@override
Widget build(BuildContext context) {
@ -217,20 +213,20 @@ class FadeThroughTransition extends StatelessWidget {
}
class _ZoomedFadeInFadeOut extends StatelessWidget {
const _ZoomedFadeInFadeOut({Key key, this.animation, this.child})
const _ZoomedFadeInFadeOut({Key? key, required this.animation, this.child})
: super(key: key);
final Animation<double> animation;
final Widget child;
final Widget? child;
@override
Widget build(BuildContext context) {
return dual_transition_builder.DualTransitionBuilder(
return DualTransitionBuilder(
animation: animation,
forwardBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return _ZoomedFadeIn(
animation: animation,
@ -240,7 +236,7 @@ class _ZoomedFadeInFadeOut extends StatelessWidget {
reverseBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return _FadeOut(
child: child,
@ -255,10 +251,10 @@ class _ZoomedFadeInFadeOut extends StatelessWidget {
class _ZoomedFadeIn extends StatelessWidget {
const _ZoomedFadeIn({
this.child,
this.animation,
required this.animation,
});
final Widget child;
final Widget? child;
final Animation<double> animation;
static final CurveTween _inCurve = CurveTween(
@ -304,10 +300,10 @@ class _ZoomedFadeIn extends StatelessWidget {
class _FadeOut extends StatelessWidget {
const _FadeOut({
this.child,
this.animation,
required this.animation,
});
final Widget child;
final Widget? child;
final Animation<double> animation;
static final CurveTween _outCurve = CurveTween(

View File

@ -46,15 +46,13 @@ typedef _ModalTransitionBuilder = Widget Function(
///
/// * [ModalConfiguration], which is the configuration object used to define
/// the modal's characteristics.
Future<T> showModal<T>({
@required BuildContext context,
Future<T?> showModal<T>({
required BuildContext context,
ModalConfiguration configuration = const FadeScaleTransitionConfiguration(),
bool useRootNavigator = true,
WidgetBuilder builder,
required WidgetBuilder builder,
}) {
assert(configuration != null);
assert(useRootNavigator != null);
String barrierLabel = configuration.barrierLabel;
String? barrierLabel = configuration.barrierLabel;
// Avoid looking up [MaterialLocalizations.of(context).modalBarrierDismissLabel]
// if there is no dismissible barrier.
if (configuration.barrierDismissible && configuration.barrierLabel == null) {
@ -89,22 +87,21 @@ class _ModalRoute<T> extends PopupRoute<T> {
this.barrierColor,
this.barrierDismissible = true,
this.barrierLabel,
this.transitionDuration,
this.reverseTransitionDuration,
_ModalTransitionBuilder transitionBuilder,
@required this.builder,
}) : assert(barrierDismissible != null),
assert(!barrierDismissible || barrierLabel != null),
required this.transitionDuration,
required this.reverseTransitionDuration,
required _ModalTransitionBuilder transitionBuilder,
required this.builder,
}) : assert(!barrierDismissible || barrierLabel != null),
_transitionBuilder = transitionBuilder;
@override
final Color barrierColor;
final Color? barrierColor;
@override
final bool barrierDismissible;
@override
final String barrierLabel;
final String? barrierLabel;
@override
final Duration transitionDuration;
@ -129,7 +126,7 @@ class _ModalRoute<T> extends PopupRoute<T> {
child: Builder(
builder: (BuildContext context) {
final Widget child = Builder(builder: builder);
return theme != null ? Theme(data: theme, child: child) : child;
return Theme(data: theme, child: child);
},
),
),
@ -178,16 +175,12 @@ abstract class ModalConfiguration {
/// application. [transitionDuration] and [reverseTransitionDuration]
/// cannot be null.
const ModalConfiguration({
@required this.barrierColor,
@required this.barrierDismissible,
required this.barrierColor,
required this.barrierDismissible,
this.barrierLabel,
@required this.transitionDuration,
@required this.reverseTransitionDuration,
}) : assert(barrierColor != null),
assert(barrierDismissible != null),
assert(!barrierDismissible || barrierLabel != null),
assert(transitionDuration != null),
assert(reverseTransitionDuration != null);
required this.transitionDuration,
required this.reverseTransitionDuration,
}) : assert(!barrierDismissible || barrierLabel != null);
/// The color to use for the modal barrier. If this is null, the barrier will
/// be transparent.
@ -197,7 +190,7 @@ abstract class ModalConfiguration {
final bool barrierDismissible;
/// The semantic label used for a dismissible barrier.
final String barrierLabel;
final String? barrierLabel;
/// The duration of the transition running forwards.
final Duration transitionDuration;

View File

@ -9,7 +9,7 @@ import 'package:flutter/scheduler.dart';
///
/// Parameter `returnValue` is the value which will be provided to [OpenContainer.onClosed]
/// when `action` is called.
typedef CloseContainerActionCallback<S> = void Function({S returnValue});
typedef CloseContainerActionCallback<S> = void Function({S? returnValue});
/// Signature for a function that creates a [Widget] in open state within an
/// [OpenContainer].
@ -74,13 +74,13 @@ typedef ClosedCallback<S> = void Function(S data);
/// * [Transitions with animated containers](https://material.io/design/motion/choreography.html#transformation)
/// in the Material spec.
@optionalTypeArgs
class OpenContainer<T extends Object> extends StatefulWidget {
class OpenContainer<T extends Object?> extends StatefulWidget {
/// Creates an [OpenContainer].
///
/// All arguments except for [key] must not be null. The arguments
/// [openBuilder] and [closedBuilder] are required.
const OpenContainer({
Key key,
Key? key,
this.closedColor = Colors.white,
this.openColor = Colors.white,
this.middleColor,
@ -91,25 +91,14 @@ class OpenContainer<T extends Object> extends StatefulWidget {
),
this.openShape = const RoundedRectangleBorder(),
this.onClosed,
@required this.closedBuilder,
@required this.openBuilder,
required this.closedBuilder,
required this.openBuilder,
this.tappable = true,
this.transitionDuration = const Duration(milliseconds: 300),
this.transitionType = ContainerTransitionType.fade,
this.useRootNavigator = false,
this.routeSettings,
}) : assert(closedColor != null),
assert(openColor != null),
assert(closedElevation != null),
assert(openElevation != null),
assert(closedShape != null),
assert(openShape != null),
assert(closedBuilder != null),
assert(openBuilder != null),
assert(tappable != null),
assert(transitionType != null),
assert(useRootNavigator != null),
super(key: key);
}) : super(key: key);
/// Background color of the container while it is closed.
///
@ -147,7 +136,7 @@ class OpenContainer<T extends Object> extends StatefulWidget {
/// See also:
///
/// * [Material.color], which is used to implement this property.
final Color middleColor;
final Color? middleColor;
/// Elevation of the container while it is closed.
///
@ -208,7 +197,7 @@ class OpenContainer<T extends Object> extends StatefulWidget {
///
/// If no value is returned via [Navigator.pop] or [OpenContainer.openBuilder.action],
/// `null` will be returned by default.
final ClosedCallback<T> onClosed;
final ClosedCallback<T?>? onClosed;
/// Called to obtain the child for the container in the closed state.
///
@ -259,13 +248,13 @@ class OpenContainer<T extends Object> extends StatefulWidget {
final bool useRootNavigator;
/// Provides additional data to the [openBuilder] route pushed by the Navigator.
final RouteSettings routeSettings;
final RouteSettings? routeSettings;
@override
_OpenContainerState<T> createState() => _OpenContainerState<T>();
}
class _OpenContainerState<T> extends State<OpenContainer<T>> {
class _OpenContainerState<T> extends State<OpenContainer<T?>> {
// Key used in [_OpenContainerRoute] to hide the widget returned by
// [OpenContainer.openBuilder] in the source route while the container is
// opening/open. A copy of that widget is included in the
@ -281,7 +270,7 @@ class _OpenContainerState<T> extends State<OpenContainer<T>> {
Future<void> openContainer() async {
final Color middleColor =
widget.middleColor ?? Theme.of(context).canvasColor;
final T data = await Navigator.of(
final T? data = await Navigator.of(
context,
rootNavigator: widget.useRootNavigator,
).push(_OpenContainerRoute<T>(
@ -302,7 +291,7 @@ class _OpenContainerState<T> extends State<OpenContainer<T>> {
routeSettings: widget.routeSettings,
));
if (widget.onClosed != null) {
widget.onClosed(data);
widget.onClosed!(data);
}
}
@ -342,11 +331,11 @@ class _OpenContainerState<T> extends State<OpenContainer<T>> {
/// `isVisible` is ignored).
class _Hideable extends StatefulWidget {
const _Hideable({
Key key,
Key? key,
this.child,
}) : super(key: key);
final Widget child;
final Widget? child;
@override
State<_Hideable> createState() => _HideableState();
@ -354,9 +343,9 @@ class _Hideable extends StatefulWidget {
class _HideableState extends State<_Hideable> {
/// When non-null the child is replaced by a [SizedBox] of the set size.
Size get placeholderSize => _placeholderSize;
Size _placeholderSize;
set placeholderSize(Size value) {
Size? get placeholderSize => _placeholderSize;
Size? _placeholderSize;
set placeholderSize(Size? value) {
if (_placeholderSize == value) {
return;
}
@ -372,7 +361,6 @@ class _HideableState extends State<_Hideable> {
bool get isVisible => _visible;
bool _visible = true;
set isVisible(bool value) {
assert(value != null);
if (_visible == value) {
return;
}
@ -400,33 +388,22 @@ class _HideableState extends State<_Hideable> {
class _OpenContainerRoute<T> extends ModalRoute<T> {
_OpenContainerRoute({
@required this.closedColor,
@required this.openColor,
@required this.middleColor,
@required double closedElevation,
@required this.openElevation,
@required ShapeBorder closedShape,
@required this.openShape,
@required this.closedBuilder,
@required this.openBuilder,
@required this.hideableKey,
@required this.closedBuilderKey,
@required this.transitionDuration,
@required this.transitionType,
@required this.useRootNavigator,
@required RouteSettings routeSettings,
}) : assert(closedColor != null),
assert(openColor != null),
assert(closedElevation != null),
assert(openElevation != null),
assert(closedShape != null),
assert(openBuilder != null),
assert(closedBuilder != null),
assert(hideableKey != null),
assert(closedBuilderKey != null),
assert(transitionType != null),
assert(useRootNavigator != null),
_elevationTween = Tween<double>(
required this.closedColor,
required this.openColor,
required this.middleColor,
required double closedElevation,
required this.openElevation,
required ShapeBorder closedShape,
required this.openShape,
required this.closedBuilder,
required this.openBuilder,
required this.hideableKey,
required this.closedBuilderKey,
required this.transitionDuration,
required this.transitionType,
required this.useRootNavigator,
required RouteSettings? routeSettings,
}) : _elevationTween = Tween<double>(
begin: closedElevation,
end: openElevation,
),
@ -444,21 +421,21 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
_openOpacityTween = _getOpenOpacityTween(transitionType),
super(settings: routeSettings);
static _FlippableTweenSequence<Color> _getColorTween({
@required ContainerTransitionType transitionType,
@required Color closedColor,
@required Color openColor,
@required Color middleColor,
static _FlippableTweenSequence<Color?> _getColorTween({
required ContainerTransitionType transitionType,
required Color closedColor,
required Color openColor,
required Color middleColor,
}) {
switch (transitionType) {
case ContainerTransitionType.fade:
return _FlippableTweenSequence<Color>(
<TweenSequenceItem<Color>>[
return _FlippableTweenSequence<Color?>(
<TweenSequenceItem<Color?>>[
TweenSequenceItem<Color>(
tween: ConstantTween<Color>(closedColor),
weight: 1 / 5,
),
TweenSequenceItem<Color>(
TweenSequenceItem<Color?>(
tween: ColorTween(begin: closedColor, end: openColor),
weight: 1 / 5,
),
@ -469,20 +446,19 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
],
);
case ContainerTransitionType.fadeThrough:
return _FlippableTweenSequence<Color>(
<TweenSequenceItem<Color>>[
TweenSequenceItem<Color>(
return _FlippableTweenSequence<Color?>(
<TweenSequenceItem<Color?>>[
TweenSequenceItem<Color?>(
tween: ColorTween(begin: closedColor, end: middleColor),
weight: 1 / 5,
),
TweenSequenceItem<Color>(
TweenSequenceItem<Color?>(
tween: ColorTween(begin: middleColor, end: openColor),
weight: 4 / 5,
),
],
);
}
return null; // unreachable
}
static _FlippableTweenSequence<double> _getClosedOpacityTween(
@ -497,7 +473,6 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
),
],
);
break;
case ContainerTransitionType.fadeThrough:
return _FlippableTweenSequence<double>(
<TweenSequenceItem<double>>[
@ -511,9 +486,7 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
),
],
);
break;
}
return null; // unreachable
}
static _FlippableTweenSequence<double> _getOpenOpacityTween(
@ -536,7 +509,6 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
),
],
);
break;
case ContainerTransitionType.fadeThrough:
return _FlippableTweenSequence<double>(
<TweenSequenceItem<double>>[
@ -550,9 +522,7 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
),
],
);
break;
}
return null; // unreachable
}
final Color closedColor;
@ -579,11 +549,11 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
final ShapeBorderTween _shapeTween;
final _FlippableTweenSequence<double> _closedOpacityTween;
final _FlippableTweenSequence<double> _openOpacityTween;
final _FlippableTweenSequence<Color> _colorTween;
final _FlippableTweenSequence<Color?> _colorTween;
static final TweenSequence<Color> _scrimFadeInTween = TweenSequence<Color>(
<TweenSequenceItem<Color>>[
TweenSequenceItem<Color>(
static final TweenSequence<Color?> _scrimFadeInTween = TweenSequence<Color?>(
<TweenSequenceItem<Color?>>[
TweenSequenceItem<Color?>(
tween: ColorTween(begin: Colors.transparent, end: Colors.black54),
weight: 1 / 5,
),
@ -593,7 +563,7 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
),
],
);
static final Tween<Color> _scrimFadeOutTween = ColorTween(
static final Tween<Color?> _scrimFadeOutTween = ColorTween(
begin: Colors.transparent,
end: Colors.black54,
);
@ -608,14 +578,14 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
// the bounds of the enclosing [Navigator].
final RectTween _rectTween = RectTween();
AnimationStatus _lastAnimationStatus;
AnimationStatus _currentAnimationStatus;
AnimationStatus? _lastAnimationStatus;
AnimationStatus? _currentAnimationStatus;
@override
TickerFuture didPush() {
_takeMeasurements(navigatorContext: hideableKey.currentContext);
_takeMeasurements(navigatorContext: hideableKey.currentContext!);
animation.addStatusListener((AnimationStatus status) {
animation!.addStatusListener((AnimationStatus status) {
_lastAnimationStatus = _currentAnimationStatus;
_currentAnimationStatus = status;
switch (status) {
@ -635,9 +605,9 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
}
@override
bool didPop(T result) {
bool didPop(T? result) {
_takeMeasurements(
navigatorContext: subtreeContext,
navigatorContext: subtreeContext!,
delayForSourceRoute: true,
);
return super.didPop(result);
@ -645,44 +615,44 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
@override
void dispose() {
if (hideableKey?.currentState?.isVisible == false) {
if (hideableKey.currentState?.isVisible == false) {
// This route may be disposed without dismissing its animation if it is
// removed by the navigator.
SchedulerBinding.instance
SchedulerBinding.instance!
.addPostFrameCallback((Duration d) => _toggleHideable(hide: false));
}
super.dispose();
}
void _toggleHideable({bool hide}) {
if (hideableKey?.currentState != null) {
hideableKey.currentState
void _toggleHideable({required bool hide}) {
if (hideableKey.currentState != null) {
hideableKey.currentState!
..placeholderSize = null
..isVisible = !hide;
}
}
void _takeMeasurements({
BuildContext navigatorContext,
required BuildContext navigatorContext,
bool delayForSourceRoute = false,
}) {
final RenderBox navigator = Navigator.of(
navigatorContext,
rootNavigator: useRootNavigator,
).context.findRenderObject();
).context.findRenderObject() as RenderBox;
final Size navSize = _getSize(navigator);
_rectTween.end = Offset.zero & navSize;
void takeMeasurementsInSourceRoute([Duration _]) {
void takeMeasurementsInSourceRoute([Duration? _]) {
if (!navigator.attached || hideableKey.currentContext == null) {
return;
}
_rectTween.begin = _getRect(hideableKey, navigator);
hideableKey.currentState.placeholderSize = _rectTween.begin.size;
hideableKey.currentState!.placeholderSize = _rectTween.begin!.size;
}
if (delayForSourceRoute) {
SchedulerBinding.instance
SchedulerBinding.instance!
.addPostFrameCallback(takeMeasurementsInSourceRoute);
} else {
takeMeasurementsInSourceRoute();
@ -690,7 +660,7 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
}
Size _getSize(RenderBox render) {
assert(render != null && render.hasSize);
assert(render.hasSize);
return render.size;
}
@ -698,9 +668,10 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
// coordinate system of `ancestor`.
Rect _getRect(GlobalKey key, RenderBox ancestor) {
assert(key.currentContext != null);
assert(ancestor != null && ancestor.hasSize);
final RenderBox render = key.currentContext.findRenderObject();
assert(render != null && render.hasSize);
assert(ancestor.hasSize);
final RenderBox render =
key.currentContext!.findRenderObject() as RenderBox;
assert(render.hasSize);
return MatrixUtils.transformRect(
render.getTransformTo(ancestor),
Offset.zero & render.size,
@ -720,6 +691,8 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
case AnimationStatus.reverse:
isInProgress = true;
break;
case null:
break;
}
switch (_lastAnimationStatus) {
case AnimationStatus.completed:
@ -730,12 +703,14 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
case AnimationStatus.reverse:
wasInProgress = true;
break;
case null:
break;
}
return wasInProgress && isInProgress;
}
void closeContainer({T returnValue}) {
Navigator.of(subtreeContext).pop(returnValue);
void closeContainer({T? returnValue}) {
Navigator.of(subtreeContext!).pop(returnValue);
}
@override
@ -748,7 +723,7 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
alignment: Alignment.topLeft,
child: AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
builder: (BuildContext context, Widget? child) {
if (animation.isCompleted) {
return SizedBox.expand(
child: Material(
@ -771,9 +746,9 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
reverseCurve:
_transitionWasInterrupted ? null : Curves.fastOutSlowIn.flipped,
);
TweenSequence<Color> colorTween;
TweenSequence<double> closedOpacityTween, openOpacityTween;
Animatable<Color> scrimTween;
TweenSequence<Color?>? colorTween;
TweenSequence<double>? closedOpacityTween, openOpacityTween;
Animatable<Color?>? scrimTween;
switch (animation.status) {
case AnimationStatus.dismissed:
case AnimationStatus.forward:
@ -804,10 +779,10 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
assert(openOpacityTween != null);
assert(scrimTween != null);
final Rect rect = _rectTween.evaluate(curvedAnimation);
final Rect rect = _rectTween.evaluate(curvedAnimation)!;
return SizedBox.expand(
child: Container(
color: scrimTween.evaluate(curvedAnimation),
color: scrimTween!.evaluate(curvedAnimation),
child: Align(
alignment: Alignment.topLeft,
child: Transform.translate(
@ -818,7 +793,7 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
child: Material(
clipBehavior: Clip.antiAlias,
animationDuration: Duration.zero,
color: colorTween.evaluate(animation),
color: colorTween!.evaluate(animation),
shape: _shapeTween.evaluate(curvedAnimation),
elevation: _elevationTween.evaluate(curvedAnimation),
child: Stack(
@ -829,13 +804,13 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
fit: BoxFit.fitWidth,
alignment: Alignment.topLeft,
child: SizedBox(
width: _rectTween.begin.width,
height: _rectTween.begin.height,
width: _rectTween.begin!.width,
height: _rectTween.begin!.height,
child: (hideableKey.currentState?.isInTree ??
false)
? null
: Opacity(
opacity: closedOpacityTween
opacity: closedOpacityTween!
.evaluate(animation),
child: Builder(
key: closedBuilderKey,
@ -854,10 +829,10 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
fit: BoxFit.fitWidth,
alignment: Alignment.topLeft,
child: SizedBox(
width: _rectTween.end.width,
height: _rectTween.end.height,
width: _rectTween.end!.width,
height: _rectTween.end!.height,
child: Opacity(
opacity: openOpacityTween.evaluate(animation),
opacity: openOpacityTween!.evaluate(animation),
child: Builder(
key: _openBuilderKey,
builder: (BuildContext context) {
@ -884,7 +859,7 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
bool get maintainState => true;
@override
Color get barrierColor => null;
Color? get barrierColor => null;
@override
bool get opaque => true;
@ -893,16 +868,16 @@ class _OpenContainerRoute<T> extends ModalRoute<T> {
bool get barrierDismissible => false;
@override
String get barrierLabel => null;
String? get barrierLabel => null;
}
class _FlippableTweenSequence<T> extends TweenSequence<T> {
_FlippableTweenSequence(this._items) : super(_items);
final List<TweenSequenceItem<T>> _items;
_FlippableTweenSequence<T> _flipped;
_FlippableTweenSequence<T>? _flipped;
_FlippableTweenSequence<T> get flipped {
_FlippableTweenSequence<T>? get flipped {
if (_flipped == null) {
final List<TweenSequenceItem<T>> newItems = <TweenSequenceItem<T>>[];
for (int i = 0; i < _items.length; i++) {

View File

@ -18,14 +18,11 @@ class _ChildEntry {
/// The [primaryController], [secondaryController], [transition] and
/// [widgetChild] parameters must not be null.
_ChildEntry({
@required this.primaryController,
@required this.secondaryController,
@required this.transition,
@required this.widgetChild,
}) : assert(primaryController != null),
assert(secondaryController != null),
assert(widgetChild != null),
assert(transition != null);
required this.primaryController,
required this.secondaryController,
required this.transition,
required this.widgetChild,
});
/// The animation controller for the child's transition.
final AnimationController primaryController;
@ -172,17 +169,13 @@ class PageTransitionSwitcher extends StatefulWidget {
/// The [duration], [reverse], and [transitionBuilder] parameters
/// must not be null.
const PageTransitionSwitcher({
Key key,
Key? key,
this.duration = const Duration(milliseconds: 300),
this.reverse = false,
@required this.transitionBuilder,
required this.transitionBuilder,
this.layoutBuilder = defaultLayoutBuilder,
this.child,
}) : assert(duration != null),
assert(reverse != null),
assert(transitionBuilder != null),
assert(layoutBuilder != null),
super(key: key);
}) : super(key: key);
/// The current child widget to display.
///
@ -195,7 +188,7 @@ class PageTransitionSwitcher extends StatefulWidget {
///
/// The child is considered to be "new" if it has a different type or [Key]
/// (see [Widget.canUpdate]).
final Widget child;
final Widget? child;
/// The duration of the transition from the old [child] value to the new one.
///
@ -285,7 +278,7 @@ class PageTransitionSwitcher extends StatefulWidget {
class _PageTransitionSwitcherState extends State<PageTransitionSwitcher>
with TickerProviderStateMixin {
final List<_ChildEntry> _activeEntries = <_ChildEntry>[];
_ChildEntry _currentEntry;
_ChildEntry? _currentEntry;
int _childNumber = 0;
@override
@ -308,30 +301,30 @@ class _PageTransitionSwitcherState extends State<PageTransitionSwitcher>
final bool hasOldChild = _currentEntry != null;
if (hasNewChild != hasOldChild ||
hasNewChild &&
!Widget.canUpdate(widget.child, _currentEntry.widgetChild)) {
!Widget.canUpdate(widget.child!, _currentEntry!.widgetChild)) {
// Child has changed, fade current entry out and add new entry.
_childNumber += 1;
_addEntryForNewChild(shouldAnimate: true);
} else if (_currentEntry != null) {
assert(hasOldChild && hasNewChild);
assert(Widget.canUpdate(widget.child, _currentEntry.widgetChild));
assert(Widget.canUpdate(widget.child!, _currentEntry!.widgetChild));
// Child has been updated. Make sure we update the child widget and
// transition in _currentEntry even though we're not going to start a new
// animation, but keep the key from the old transition so that we
// update the transition instead of replacing it.
_currentEntry.widgetChild = widget.child;
_updateTransitionForEntry(_currentEntry); // uses entry.widgetChild
_currentEntry!.widgetChild = widget.child!;
_updateTransitionForEntry(_currentEntry!); // uses entry.widgetChild
}
}
void _addEntryForNewChild({@required bool shouldAnimate}) {
void _addEntryForNewChild({required bool shouldAnimate}) {
assert(shouldAnimate || _currentEntry == null);
if (_currentEntry != null) {
assert(shouldAnimate);
if (widget.reverse) {
_currentEntry.primaryController.reverse();
_currentEntry!.primaryController.reverse();
} else {
_currentEntry.secondaryController.forward();
_currentEntry!.secondaryController.forward();
}
_currentEntry = null;
}
@ -359,35 +352,31 @@ class _PageTransitionSwitcherState extends State<PageTransitionSwitcher>
primaryController.value = 1.0;
}
_currentEntry = _newEntry(
child: widget.child,
child: widget.child!,
primaryController: primaryController,
secondaryController: secondaryController,
builder: widget.transitionBuilder,
);
if (widget.reverse && _activeEntries.isNotEmpty) {
// Add below old child.
_activeEntries.insert(_activeEntries.length - 1, _currentEntry);
_activeEntries.insert(_activeEntries.length - 1, _currentEntry!);
} else {
// Add on top of old child.
_activeEntries.add(_currentEntry);
_activeEntries.add(_currentEntry!);
}
}
_ChildEntry _newEntry({
@required Widget child,
@required PageTransitionSwitcherTransitionBuilder builder,
@required AnimationController primaryController,
@required AnimationController secondaryController,
required Widget child,
required PageTransitionSwitcherTransitionBuilder builder,
required AnimationController primaryController,
required AnimationController secondaryController,
}) {
final Widget transition = builder(
child,
primaryController,
secondaryController,
);
assert(
transition != null,
'PageTransitionSwitcher.builder must not return null.',
);
final _ChildEntry entry = _ChildEntry(
widgetChild: child,
transition: KeyedSubtree.wrap(
@ -426,10 +415,6 @@ class _PageTransitionSwitcherState extends State<PageTransitionSwitcher>
entry.primaryController,
entry.secondaryController,
);
assert(
transition != null,
'PageTransitionSwitcher.builder must not return null.',
);
entry.transition = KeyedSubtree(
key: entry.transition.key,
child: transition,

View File

@ -4,19 +4,9 @@
import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'
hide
decelerateEasing, // ignore: undefined_hidden_name
standardEasing, // ignore: undefined_hidden_name
accelerateEasing; // ignore: undefined_hidden_name
// TODO(goderbauer): Remove implementation import when material properly exports the file.
import 'package:flutter/src/material/curves.dart'; // ignore: implementation_imports
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
// TODO(shihaohong): Remove DualTransitionBuilder once flutter/flutter's `stable`
// branch contains DualTransitionBuilder.
import 'dual_transition_builder.dart' as dual_transition_builder;
/// Determines which type of shared axis transition is used.
enum SharedAxisTransitionType {
/// Creates a shared axis vertical (y-axis) page transition.
@ -87,9 +77,9 @@ enum SharedAxisTransitionType {
class SharedAxisPageTransitionsBuilder extends PageTransitionsBuilder {
/// Construct a [SharedAxisPageTransitionsBuilder].
const SharedAxisPageTransitionsBuilder({
@required this.transitionType,
required this.transitionType,
this.fillColor,
}) : assert(transitionType != null);
});
/// Determines which [SharedAxisTransitionType] to build.
final SharedAxisTransitionType transitionType;
@ -97,12 +87,12 @@ class SharedAxisPageTransitionsBuilder extends PageTransitionsBuilder {
/// The color to use for the background color during the transition.
///
/// This defaults to the [Theme]'s [ThemeData.canvasColor].
final Color fillColor;
final Color? fillColor;
@override
Widget buildTransitions<T>(
PageRoute<T> route,
BuildContext context,
PageRoute<T>? route,
BuildContext? context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
@ -197,14 +187,13 @@ class SharedAxisTransition extends StatelessWidget {
/// The [animation] and [secondaryAnimation] argument are required and must
/// not be null.
const SharedAxisTransition({
Key key,
@required this.animation,
@required this.secondaryAnimation,
@required this.transitionType,
Key? key,
required this.animation,
required this.secondaryAnimation,
required this.transitionType,
this.fillColor,
this.child,
}) : assert(transitionType != null),
super(key: key);
}) : super(key: key);
/// The animation that drives the [child]'s entrance and exit.
///
@ -234,23 +223,23 @@ class SharedAxisTransition extends StatelessWidget {
/// The color to use for the background color during the transition.
///
/// This defaults to the [Theme]'s [ThemeData.canvasColor].
final Color fillColor;
final Color? fillColor;
/// The widget below this widget in the tree.
///
/// This widget will transition in and out as driven by [animation] and
/// [secondaryAnimation].
final Widget child;
final Widget? child;
@override
Widget build(BuildContext context) {
final Color color = fillColor ?? Theme.of(context).canvasColor;
return dual_transition_builder.DualTransitionBuilder(
return DualTransitionBuilder(
animation: animation,
forwardBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return _EnterTransition(
animation: animation,
@ -261,7 +250,7 @@ class SharedAxisTransition extends StatelessWidget {
reverseBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return _ExitTransition(
animation: animation,
@ -271,12 +260,12 @@ class SharedAxisTransition extends StatelessWidget {
child: child,
);
},
child: dual_transition_builder.DualTransitionBuilder(
child: DualTransitionBuilder(
animation: ReverseAnimation(secondaryAnimation),
forwardBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return _EnterTransition(
animation: animation,
@ -288,7 +277,7 @@ class SharedAxisTransition extends StatelessWidget {
reverseBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return _ExitTransition(
animation: animation,
@ -305,15 +294,15 @@ class SharedAxisTransition extends StatelessWidget {
class _EnterTransition extends StatelessWidget {
const _EnterTransition({
this.animation,
this.transitionType,
required this.animation,
required this.transitionType,
this.reverse = false,
this.child,
});
final Animation<double> animation;
final SharedAxisTransitionType transitionType;
final Widget child;
final Widget? child;
final bool reverse;
static final Animatable<double> _fadeInTransition = CurveTween(
@ -343,7 +332,7 @@ class _EnterTransition extends StatelessWidget {
opacity: _fadeInTransition.animate(animation),
child: AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
builder: (BuildContext context, Widget? child) {
return Transform.translate(
offset: slideInTransition.evaluate(animation),
child: child,
@ -352,7 +341,6 @@ class _EnterTransition extends StatelessWidget {
child: child,
),
);
break;
case SharedAxisTransitionType.vertical:
final Animatable<Offset> slideInTransition = Tween<Offset>(
begin: Offset(0.0, !reverse ? 30.0 : -30.0),
@ -363,7 +351,7 @@ class _EnterTransition extends StatelessWidget {
opacity: _fadeInTransition.animate(animation),
child: AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
builder: (BuildContext context, Widget? child) {
return Transform.translate(
offset: slideInTransition.evaluate(animation),
child: child,
@ -372,7 +360,6 @@ class _EnterTransition extends StatelessWidget {
child: child,
),
);
break;
case SharedAxisTransitionType.scaled:
return FadeTransition(
opacity: _fadeInTransition.animate(animation),
@ -382,18 +369,16 @@ class _EnterTransition extends StatelessWidget {
child: child,
),
);
break;
}
return null; // unreachable
}
}
class _ExitTransition extends StatelessWidget {
const _ExitTransition({
this.animation,
this.transitionType,
required this.animation,
required this.transitionType,
this.reverse = false,
@required this.fillColor,
required this.fillColor,
this.child,
});
@ -401,7 +386,7 @@ class _ExitTransition extends StatelessWidget {
final SharedAxisTransitionType transitionType;
final bool reverse;
final Color fillColor;
final Widget child;
final Widget? child;
static final Animatable<double> _fadeOutTransition = _FlippedCurveTween(
curve: accelerateEasing,
@ -432,7 +417,7 @@ class _ExitTransition extends StatelessWidget {
color: fillColor,
child: AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
builder: (BuildContext context, Widget? child) {
return Transform.translate(
offset: slideOutTransition.evaluate(animation),
child: child,
@ -442,7 +427,6 @@ class _ExitTransition extends StatelessWidget {
),
),
);
break;
case SharedAxisTransitionType.vertical:
final Animatable<Offset> slideOutTransition = Tween<Offset>(
begin: Offset.zero,
@ -455,7 +439,7 @@ class _ExitTransition extends StatelessWidget {
color: fillColor,
child: AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
builder: (BuildContext context, Widget? child) {
return Transform.translate(
offset: slideOutTransition.evaluate(animation),
child: child,
@ -465,7 +449,6 @@ class _ExitTransition extends StatelessWidget {
),
),
);
break;
case SharedAxisTransitionType.scaled:
return FadeTransition(
opacity: _fadeOutTransition.animate(animation),
@ -478,9 +461,7 @@ class _ExitTransition extends StatelessWidget {
),
),
);
break;
}
return null; // unreachable
}
}
@ -494,9 +475,8 @@ class _ExitTransition extends StatelessWidget {
class _FlippedCurveTween extends CurveTween {
/// Creates a vertically flipped [CurveTween].
_FlippedCurveTween({
@required Curve curve,
}) : assert(curve != null),
super(curve: curve);
required Curve curve,
}) : super(curve: curve);
@override
double transform(double t) => 1.0 - super.transform(t);

View File

@ -1,10 +1,10 @@
name: animations
description: Fancy pre-built animations that can easily be integrated into any Flutter application.
version: 1.1.2
version: 2.0.0-nullsafety.0
homepage: https://github.com/flutter/packages/tree/master/packages/animations
environment:
sdk: ">=2.2.2 <3.0.0"
sdk: '>=2.12.0-0 <3.0.0'
dependencies:
flutter:
@ -13,4 +13,4 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
vector_math: ^2.0.8
vector_math: ">=2.1.0-nullsafety.5 <3.0.0"

View File

@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(shihaohong): Remove DualTransitionBuilder once flutter/flutter's `stable`
// branch contains DualTransitionBuilder.
import 'package:animations/src/dual_transition_builder.dart'
as dual_transition_builder;
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
@ -18,12 +14,12 @@ void main() {
);
await tester.pumpWidget(Center(
child: dual_transition_builder.DualTransitionBuilder(
child: DualTransitionBuilder(
animation: controller,
forwardBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return ScaleTransition(
scale: animation,
@ -33,7 +29,7 @@ void main() {
reverseBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return FadeTransition(
opacity: Tween<double>(begin: 1.0, end: 0.0).animate(animation),
@ -88,12 +84,12 @@ void main() {
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: dual_transition_builder.DualTransitionBuilder(
child: DualTransitionBuilder(
animation: controller,
forwardBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return ScaleTransition(
scale: animation,
@ -103,7 +99,7 @@ void main() {
reverseBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return FadeTransition(
opacity: Tween<double>(begin: 1.0, end: 0.0).animate(animation),
@ -150,12 +146,12 @@ void main() {
duration: const Duration(milliseconds: 300),
);
await tester.pumpWidget(Center(
child: dual_transition_builder.DualTransitionBuilder(
child: DualTransitionBuilder(
animation: controller,
forwardBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return ScaleTransition(
scale: animation,
@ -165,7 +161,7 @@ void main() {
reverseBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return FadeTransition(
opacity: Tween<double>(begin: 1.0, end: 0.0).animate(animation),
@ -216,12 +212,12 @@ void main() {
duration: const Duration(milliseconds: 300),
);
await tester.pumpWidget(Center(
child: dual_transition_builder.DualTransitionBuilder(
child: DualTransitionBuilder(
animation: controller,
forwardBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return ScaleTransition(
scale: animation,
@ -231,7 +227,7 @@ void main() {
reverseBuilder: (
BuildContext context,
Animation<double> animation,
Widget child,
Widget? child,
) {
return FadeTransition(
opacity: Tween<double>(begin: 1.0, end: 0.0).animate(animation),
@ -286,7 +282,7 @@ double _getOpacity(WidgetTester tester) {
}
class _StatefulTestWidget extends StatefulWidget {
const _StatefulTestWidget({Key key, this.name}) : super(key: key);
const _StatefulTestWidget({Key? key, required this.name}) : super(key: key);
final String name;

View File

@ -455,7 +455,7 @@ double _getOpacity(GlobalKey key, WidgetTester tester) {
matching: find.byType(FadeTransition),
);
return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
final FadeTransition transition = widget;
final FadeTransition transition = widget as FadeTransition;
return a * transition.opacity.value;
});
}
@ -466,18 +466,18 @@ double _getScale(GlobalKey key, WidgetTester tester) {
matching: find.byType(ScaleTransition),
);
return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
final ScaleTransition transition = widget;
final ScaleTransition transition = widget as ScaleTransition;
return a * transition.scale.value;
});
}
class _FlutterLogoModal extends StatefulWidget {
const _FlutterLogoModal({
Key key,
Key? key,
this.name,
}) : super(key: key);
final String name;
final String? name;
@override
_FlutterLogoModalState createState() => _FlutterLogoModalState();

View File

@ -47,7 +47,7 @@ void main() {
expect(_getOpacity(bottomRoute, tester), 1.0);
expect(find.text(topRoute), findsNothing);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pump();
@ -127,7 +127,7 @@ void main() {
navigatorKey: navigator,
),
);
navigator.currentState.pushNamed('/a');
navigator.currentState!.pushNamed('/a');
await tester.pumpAndSettle();
expect(find.text(topRoute), findsOneWidget);
@ -135,7 +135,7 @@ void main() {
expect(_getOpacity(topRoute, tester), 1.0);
expect(find.text(bottomRoute), findsNothing);
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
// Top route is full size and fully visible.
@ -223,7 +223,7 @@ void main() {
expect(find.text(bottomRoute), findsOneWidget);
expect(find.text(topRoute), findsNothing);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
// Jump to halfway point of transition.
@ -242,7 +242,7 @@ void main() {
expect(topOpacity, lessThan(1.0));
// Interrupt the transition with a pop.
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
// Noting changed.
expect(find.text(bottomRoute), findsOneWidget);
@ -288,7 +288,7 @@ void main() {
navigatorKey: navigator,
contentBuilder: (RouteSettings settings) {
return _StatefulTestWidget(
key: ValueKey<String>(settings.name),
key: ValueKey<String?>(settings.name),
name: settings.name,
);
},
@ -296,73 +296,73 @@ void main() {
);
final _StatefulTestWidgetState bottomState =
tester.state(find.byKey(const ValueKey<String>(bottomRoute)));
tester.state(find.byKey(const ValueKey<String?>(bottomRoute)));
expect(bottomState.widget.name, bottomRoute);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pump();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
final _StatefulTestWidgetState topState = tester.state(
find.byKey(const ValueKey<String>(topRoute)),
find.byKey(const ValueKey<String?>(topRoute)),
);
expect(topState.widget.name, topRoute);
await tester.pump(const Duration(milliseconds: 150));
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pumpAndSettle();
expect(
tester.state(find.byKey(
const ValueKey<String>(bottomRoute),
const ValueKey<String?>(bottomRoute),
skipOffstage: false,
)),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pump(const Duration(milliseconds: 150));
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pumpAndSettle();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(find.byKey(const ValueKey<String>(topRoute)), findsNothing);
expect(find.byKey(const ValueKey<String?>(topRoute)), findsNothing);
});
testWidgets('should keep state', (WidgetTester tester) async {
@ -433,22 +433,22 @@ void main() {
double _getOpacity(String key, WidgetTester tester) {
final Finder finder = find.ancestor(
of: find.byKey(ValueKey<String>(key)),
of: find.byKey(ValueKey<String?>(key)),
matching: find.byType(FadeTransition),
);
return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
final FadeTransition transition = widget;
final FadeTransition transition = widget as FadeTransition;
return a * transition.opacity.value;
});
}
double _getScale(String key, WidgetTester tester) {
final Finder finder = find.ancestor(
of: find.byKey(ValueKey<String>(key)),
of: find.byKey(ValueKey<String?>(key)),
matching: find.byType(ScaleTransition),
);
return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
final ScaleTransition transition = widget;
final ScaleTransition transition = widget as ScaleTransition;
return a * transition.scale.value;
});
}
@ -456,13 +456,13 @@ double _getScale(String key, WidgetTester tester) {
class _TestWidget extends StatelessWidget {
const _TestWidget({this.navigatorKey, this.contentBuilder});
final Key navigatorKey;
final _ContentBuilder contentBuilder;
final Key? navigatorKey;
final _ContentBuilder? contentBuilder;
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: navigatorKey,
navigatorKey: navigatorKey as GlobalKey<NavigatorState>?,
theme: ThemeData(
platform: TargetPlatform.android,
pageTransitionsTheme: const PageTransitionsTheme(
@ -476,11 +476,11 @@ class _TestWidget extends StatelessWidget {
settings: settings,
builder: (BuildContext context) {
return contentBuilder != null
? contentBuilder(settings)
? contentBuilder!(settings)
: Container(
child: Center(
key: ValueKey<String>(settings.name),
child: Text(settings.name),
key: ValueKey<String?>(settings.name),
child: Text(settings.name!),
),
);
},
@ -491,9 +491,9 @@ class _TestWidget extends StatelessWidget {
}
class _StatefulTestWidget extends StatefulWidget {
const _StatefulTestWidget({Key key, this.name}) : super(key: key);
const _StatefulTestWidget({Key? key, this.name}) : super(key: key);
final String name;
final String? name;
@override
State<_StatefulTestWidget> createState() => _StatefulTestWidgetState();
@ -502,7 +502,7 @@ class _StatefulTestWidget extends StatefulWidget {
class _StatefulTestWidgetState extends State<_StatefulTestWidget> {
@override
Widget build(BuildContext context) {
return Text(widget.name);
return Text(widget.name!);
}
}

View File

@ -464,7 +464,7 @@ double _getOpacity(GlobalKey key, WidgetTester tester) {
matching: find.byType(FadeTransition),
);
return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
final FadeTransition transition = widget;
final FadeTransition transition = widget as FadeTransition;
return a * transition.opacity.value;
});
}
@ -475,18 +475,18 @@ double _getScale(GlobalKey key, WidgetTester tester) {
matching: find.byType(ScaleTransition),
);
return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
final ScaleTransition transition = widget;
final ScaleTransition transition = widget as ScaleTransition;
return a * transition.scale.value;
});
}
class _FlutterLogoModal extends StatefulWidget {
const _FlutterLogoModal({
Key key,
Key? key,
this.name,
}) : super(key: key);
final String name;
final String? name;
@override
_FlutterLogoModalState createState() => _FlutterLogoModalState();
@ -516,8 +516,7 @@ class _TestModalConfiguration extends ModalConfiguration {
String barrierLabel = 'customLabel',
Duration transitionDuration = const Duration(milliseconds: 300),
Duration reverseTransitionDuration = const Duration(milliseconds: 200),
}) : assert(barrierDismissible != null),
super(
}) : super(
barrierColor: barrierColor,
barrierDismissible: barrierDismissible,
barrierLabel: barrierLabel,

View File

@ -44,7 +44,7 @@ void main() {
matching: find.byType(Material),
),
);
final Material srcMaterial = srcMaterialElement.widget;
final Material srcMaterial = srcMaterialElement.widget as Material;
expect(srcMaterial.color, Colors.green);
expect(srcMaterial.elevation, 4.0);
expect(srcMaterial.shape, shape);
@ -69,7 +69,7 @@ void main() {
matching: find.byType(Material),
),
);
final Material closedMaterial = destMaterialElement.widget;
final Material closedMaterial = destMaterialElement.widget as Material;
expect(closedMaterial.color, Colors.green);
expect(closedMaterial.elevation, 4.0);
expect(closedMaterial.shape, shape);
@ -90,7 +90,7 @@ void main() {
// Jump to the start of the fade in.
await tester.pump(const Duration(milliseconds: 60)); // 300ms * 1/5 = 60ms
final _TrackedData dataPreFade = _TrackedData(
destMaterialElement.widget,
destMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == destMaterialElement),
),
@ -107,7 +107,7 @@ void main() {
await tester
.pump(const Duration(milliseconds: 30)); // 300ms * 3/10 = 90ms
final _TrackedData dataMidFadeIn = _TrackedData(
destMaterialElement.widget,
destMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == destMaterialElement),
),
@ -128,7 +128,7 @@ void main() {
); // 300ms * 2/5 = 120ms
final _TrackedData dataPostFadeIn = _TrackedData(
destMaterialElement.widget,
destMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == destMaterialElement),
),
@ -144,7 +144,7 @@ void main() {
// Jump almost to the end of the transition.
await tester.pump(const Duration(milliseconds: 180));
final _TrackedData dataTransitionDone = _TrackedData(
destMaterialElement.widget,
destMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == destMaterialElement),
),
@ -170,7 +170,7 @@ void main() {
),
);
final _TrackedData dataOpen = _TrackedData(
finalMaterialElement.widget,
finalMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == finalMaterialElement),
),
@ -221,7 +221,7 @@ void main() {
),
);
final _TrackedData dataOpen = _TrackedData(
initialMaterialElement.widget,
initialMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == initialMaterialElement),
),
@ -245,7 +245,7 @@ void main() {
),
);
final _TrackedData dataTransitionStart = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -261,7 +261,7 @@ void main() {
// Jump to start of fade out: 1/5 of 300.
await tester.pump(const Duration(milliseconds: 60)); // 300 * 1/5 = 60
final _TrackedData dataPreFadeOut = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -277,7 +277,7 @@ void main() {
// Jump to the middle of the fade out.
await tester.pump(const Duration(milliseconds: 30)); // 300 * 3/10 = 90
final _TrackedData dataMidpoint = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -295,7 +295,7 @@ void main() {
// Jump to the end of the fade out.
await tester.pump(const Duration(milliseconds: 30)); // 300 * 2/5 = 120
final _TrackedData dataPostFadeOut = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -311,7 +311,7 @@ void main() {
// Jump almost to the end of the transition.
await tester.pump(const Duration(milliseconds: 180));
final _TrackedData dataTransitionDone = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -337,7 +337,7 @@ void main() {
),
);
final _TrackedData dataClosed = _TrackedData(
finalMaterialElement.widget,
finalMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == finalMaterialElement),
),
@ -388,7 +388,7 @@ void main() {
matching: find.byType(Material),
),
);
final Material srcMaterial = srcMaterialElement.widget;
final Material srcMaterial = srcMaterialElement.widget as Material;
expect(srcMaterial.color, Colors.green);
expect(srcMaterial.elevation, 4.0);
expect(srcMaterial.shape, shape);
@ -413,7 +413,7 @@ void main() {
matching: find.byType(Material),
),
);
final Material closedMaterial = destMaterialElement.widget;
final Material closedMaterial = destMaterialElement.widget as Material;
expect(closedMaterial.color, Colors.green);
expect(closedMaterial.elevation, 4.0);
expect(closedMaterial.shape, shape);
@ -434,7 +434,7 @@ void main() {
// The fade-out takes 1/5 of 300ms. Let's jump to the midpoint of that.
await tester.pump(const Duration(milliseconds: 30)); // 300ms * 1/10 = 30ms
final _TrackedData dataMidFadeOut = _TrackedData(
destMaterialElement.widget,
destMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == destMaterialElement),
),
@ -452,7 +452,7 @@ void main() {
// Let's jump to the crossover point at 1/5 of 300ms.
await tester.pump(const Duration(milliseconds: 30)); // 300ms * 1/5 = 60ms
final _TrackedData dataMidpoint = _TrackedData(
destMaterialElement.widget,
destMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == destMaterialElement),
),
@ -469,7 +469,7 @@ void main() {
// Let's jump to the middle of the fade-in at 3/5 of 300ms
await tester.pump(const Duration(milliseconds: 120)); // 300ms * 3/5 = 180ms
final _TrackedData dataMidFadeIn = _TrackedData(
destMaterialElement.widget,
destMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == destMaterialElement),
),
@ -487,7 +487,7 @@ void main() {
// Let's jump almost to the end of the transition.
await tester.pump(const Duration(milliseconds: 120));
final _TrackedData dataTransitionDone = _TrackedData(
destMaterialElement.widget,
destMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == destMaterialElement),
),
@ -518,7 +518,7 @@ void main() {
),
);
final _TrackedData dataOpen = _TrackedData(
finalMaterialElement.widget,
finalMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == finalMaterialElement),
),
@ -567,7 +567,7 @@ void main() {
),
);
final _TrackedData dataOpen = _TrackedData(
initialMaterialElement.widget,
initialMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == initialMaterialElement),
),
@ -591,7 +591,7 @@ void main() {
),
);
final _TrackedData dataTransitionStart = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -606,7 +606,7 @@ void main() {
// Jump to mid-point of fade-out: 1/10 of 300ms.
await tester.pump(const Duration(milliseconds: 30)); // 300ms * 1/10 = 30ms
final _TrackedData dataMidFadeOut = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -627,7 +627,7 @@ void main() {
// Let's jump to the crossover point at 1/5 of 300ms.
await tester.pump(const Duration(milliseconds: 30)); // 300ms * 1/5 = 60ms
final _TrackedData dataMidpoint = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -644,7 +644,7 @@ void main() {
// Let's jump to the middle of the fade-in at 3/5 of 300ms
await tester.pump(const Duration(milliseconds: 120)); // 300ms * 3/5 = 180ms
final _TrackedData dataMidFadeIn = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -662,7 +662,7 @@ void main() {
// Let's jump almost to the end of the transition.
await tester.pump(const Duration(milliseconds: 120));
final _TrackedData dataTransitionDone = _TrackedData(
materialElement.widget,
materialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == materialElement),
),
@ -692,7 +692,7 @@ void main() {
),
);
final _TrackedData dataClosed = _TrackedData(
finalMaterialElement.widget,
finalMaterialElement.widget as Material,
tester.getRect(
find.byElementPredicate((Element e) => e == finalMaterialElement),
),
@ -731,7 +731,7 @@ void main() {
});
testWidgets('Action callbacks work', (WidgetTester tester) async {
VoidCallback open, close;
late VoidCallback open, close;
await tester.pumpWidget(_boilerplate(
child: Center(
child: OpenContainer(
@ -805,7 +805,7 @@ void main() {
});
testWidgets('closed widget keeps state', (WidgetTester tester) async {
VoidCallback open;
late VoidCallback open;
await tester.pumpWidget(_boilerplate(
child: Center(
child: OpenContainer(
@ -1530,9 +1530,9 @@ void main() {
testWidgets(
'onClosed callback receives popped value when container has closed',
(WidgetTester tester) async {
bool value = false;
bool? value = false;
final Widget openContainer = OpenContainer<bool>(
onClosed: (bool poppedValue) {
onClosed: (bool? poppedValue) {
value = poppedValue;
},
closedBuilder: (BuildContext context, VoidCallback action) {
@ -1573,9 +1573,9 @@ void main() {
});
Widget _createRootNavigatorTest({
@required Key appKey,
@required Key nestedNavigatorKey,
@required bool useRootNavigator,
required Key appKey,
required Key nestedNavigatorKey,
required bool useRootNavigator,
}) {
return Center(
child: SizedBox(
@ -1729,7 +1729,7 @@ void main() {
// equal to the RouteSettings passed to the OpenContainer
final ModalRoute<dynamic> modalRoute = ModalRoute.of(
tester.element(find.text('Open')),
);
)!;
expect(modalRoute.settings, routeSettings);
},
);
@ -1781,9 +1781,9 @@ Color _getScrimColor(WidgetTester tester) {
}
void _expectMaterialPropertiesHaveAdvanced({
@required _TrackedData biggerMaterial,
@required _TrackedData smallerMaterial,
@required WidgetTester tester,
required _TrackedData biggerMaterial,
required _TrackedData smallerMaterial,
required WidgetTester tester,
}) {
expect(
biggerMaterial.material.elevation,
@ -1814,15 +1814,16 @@ class _TrackedData {
}
double _getRadius(Material material) {
final RoundedRectangleBorder shape = material.shape;
final RoundedRectangleBorder? shape =
material.shape as RoundedRectangleBorder?;
if (shape == null) {
return 0.0;
}
final BorderRadius radius = shape.borderRadius;
final BorderRadius radius = shape.borderRadius as BorderRadius;
return radius.topRight.x;
}
Widget _boilerplate({@required Widget child}) {
Widget _boilerplate({required Widget child}) {
return MaterialApp(
home: Scaffold(
body: child,
@ -1831,7 +1832,7 @@ Widget _boilerplate({@required Widget child}) {
}
class _SizableContainer extends StatefulWidget {
const _SizableContainer({this.initialSize, this.child});
const _SizableContainer({required this.initialSize, required this.child});
final double initialSize;
final Widget child;
@ -1842,7 +1843,7 @@ class _SizableContainer extends StatefulWidget {
}
class _SizableContainerState extends State<_SizableContainer> {
_SizableContainerState({double size}) : _size = size;
_SizableContainerState({required double size}) : _size = size;
double get size => _size;
double _size;

View File

@ -585,7 +585,7 @@ void main() {
}
class StatefulTestWidget extends StatefulWidget {
const StatefulTestWidget({Key key}) : super(key: key);
const StatefulTestWidget({Key? key}) : super(key: key);
@override
StatefulTestWidgetState createState() => StatefulTestWidgetState();

View File

@ -63,7 +63,7 @@ void main() {
expect(_getOpacity(bottomRoute, tester), 1.0);
expect(find.text(topRoute), findsNothing);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pump();
@ -103,7 +103,7 @@ void main() {
// Top route is still invisible, but moving towards the left.
expect(find.text(topRoute), findsOneWidget);
expect(_getOpacity(topRoute, tester), 0.0);
double topOffset = _getTranslationOffset(
double? topOffset = _getTranslationOffset(
topRoute,
tester,
SharedAxisTransitionType.horizontal,
@ -174,7 +174,7 @@ void main() {
),
);
navigator.currentState.pushNamed('/a');
navigator.currentState!.pushNamed('/a');
await tester.pumpAndSettle();
expect(find.text(topRoute), findsOneWidget);
@ -189,7 +189,7 @@ void main() {
expect(_getOpacity(topRoute, tester), 1.0);
expect(find.text(bottomRoute), findsNothing);
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
// Top route is is not offset and fully visible.
@ -228,7 +228,7 @@ void main() {
expect(find.text(bottomRoute), findsOneWidget);
expect(_getOpacity(bottomRoute, tester),
moreOrLessEquals(0, epsilon: 0.005));
double bottomOffset = _getTranslationOffset(
double? bottomOffset = _getTranslationOffset(
bottomRoute,
tester,
SharedAxisTransitionType.horizontal,
@ -300,7 +300,7 @@ void main() {
expect(find.text(bottomRoute), findsOneWidget);
expect(find.text(topRoute), findsNothing);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
// Jump to halfway point of transition.
@ -308,7 +308,7 @@ void main() {
// Bottom route is fully faded out.
expect(find.text(bottomRoute), findsOneWidget);
expect(_getOpacity(bottomRoute, tester), 0.0);
final double halfwayBottomOffset = _getTranslationOffset(
final double? halfwayBottomOffset = _getTranslationOffset(
bottomRoute,
tester,
SharedAxisTransitionType.horizontal,
@ -318,7 +318,7 @@ void main() {
// Top route is fading/coming in.
expect(find.text(topRoute), findsOneWidget);
final double halfwayTopOffset = _getTranslationOffset(
final double? halfwayTopOffset = _getTranslationOffset(
topRoute,
tester,
SharedAxisTransitionType.horizontal,
@ -330,7 +330,7 @@ void main() {
expect(halfwayTopOpacity, lessThan(1.0));
// Interrupt the transition with a pop.
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
// Nothing should change.
@ -426,8 +426,8 @@ void main() {
navigatorKey: navigator,
contentBuilder: (RouteSettings settings) {
return _StatefulTestWidget(
key: ValueKey<String>(settings.name),
name: settings.name,
key: ValueKey<String?>(settings.name),
name: settings.name!,
);
},
transitionType: SharedAxisTransitionType.horizontal,
@ -435,74 +435,74 @@ void main() {
);
final _StatefulTestWidgetState bottomState = tester.state(
find.byKey(const ValueKey<String>(bottomRoute)),
find.byKey(const ValueKey<String?>(bottomRoute)),
);
expect(bottomState.widget.name, bottomRoute);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pump();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
final _StatefulTestWidgetState topState = tester.state(
find.byKey(const ValueKey<String>(topRoute)),
find.byKey(const ValueKey<String?>(topRoute)),
);
expect(topState.widget.name, topRoute);
await tester.pump(const Duration(milliseconds: 150));
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pumpAndSettle();
expect(
tester.state(find.byKey(
const ValueKey<String>(bottomRoute),
const ValueKey<String?>(bottomRoute),
skipOffstage: false,
)),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pump(const Duration(milliseconds: 150));
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pumpAndSettle();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(find.byKey(const ValueKey<String>(topRoute)), findsNothing);
expect(find.byKey(const ValueKey<String?>(topRoute)), findsNothing);
},
);
@ -525,21 +525,21 @@ void main() {
Finder fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/')),
of: find.byKey(const ValueKey<String?>('/')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
expect(tester.widget<Container>(fillContainerFinder).color,
defaultFillColor);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pumpAndSettle();
fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/a')),
of: find.byKey(const ValueKey<String?>('/a')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
@ -564,20 +564,20 @@ void main() {
Finder fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/')),
of: find.byKey(const ValueKey<String?>('/')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
expect(tester.widget<Container>(fillContainerFinder).color, Colors.green);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pumpAndSettle();
fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/a')),
of: find.byKey(const ValueKey<String?>('/a')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
@ -704,7 +704,7 @@ void main() {
expect(_getOpacity(bottomRoute, tester), 1.0);
expect(find.text(topRoute), findsNothing);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pump();
@ -744,7 +744,7 @@ void main() {
// Top route is still invisible, but moving up.
expect(find.text(topRoute), findsOneWidget);
expect(_getOpacity(topRoute, tester), 0.0);
double topOffset = _getTranslationOffset(
double? topOffset = _getTranslationOffset(
topRoute,
tester,
SharedAxisTransitionType.vertical,
@ -815,7 +815,7 @@ void main() {
),
);
navigator.currentState.pushNamed('/a');
navigator.currentState!.pushNamed('/a');
await tester.pumpAndSettle();
expect(find.text(topRoute), findsOneWidget);
@ -830,7 +830,7 @@ void main() {
expect(_getOpacity(topRoute, tester), 1.0);
expect(find.text(bottomRoute), findsNothing);
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
// Top route is is not offset and fully visible.
@ -871,7 +871,7 @@ void main() {
_getOpacity(bottomRoute, tester),
moreOrLessEquals(0, epsilon: 0.005),
);
double bottomOffset = _getTranslationOffset(
double? bottomOffset = _getTranslationOffset(
bottomRoute,
tester,
SharedAxisTransitionType.vertical,
@ -943,7 +943,7 @@ void main() {
expect(find.text(bottomRoute), findsOneWidget);
expect(find.text(topRoute), findsNothing);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
// Jump to halfway point of transition.
@ -951,7 +951,7 @@ void main() {
// Bottom route is fully faded out.
expect(find.text(bottomRoute), findsOneWidget);
expect(_getOpacity(bottomRoute, tester), 0.0);
final double halfwayBottomOffset = _getTranslationOffset(
final double? halfwayBottomOffset = _getTranslationOffset(
bottomRoute,
tester,
SharedAxisTransitionType.vertical,
@ -961,7 +961,7 @@ void main() {
// Top route is fading/coming in.
expect(find.text(topRoute), findsOneWidget);
final double halfwayTopOffset = _getTranslationOffset(
final double? halfwayTopOffset = _getTranslationOffset(
topRoute,
tester,
SharedAxisTransitionType.vertical,
@ -973,7 +973,7 @@ void main() {
expect(halfwayTopOpacity, lessThan(1.0));
// Interrupt the transition with a pop.
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
// Nothing should change.
@ -1069,8 +1069,8 @@ void main() {
navigatorKey: navigator,
contentBuilder: (RouteSettings settings) {
return _StatefulTestWidget(
key: ValueKey<String>(settings.name),
name: settings.name,
key: ValueKey<String?>(settings.name),
name: settings.name!,
);
},
transitionType: SharedAxisTransitionType.vertical,
@ -1078,74 +1078,74 @@ void main() {
);
final _StatefulTestWidgetState bottomState = tester.state(
find.byKey(const ValueKey<String>(bottomRoute)),
find.byKey(const ValueKey<String?>(bottomRoute)),
);
expect(bottomState.widget.name, bottomRoute);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pump();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
final _StatefulTestWidgetState topState = tester.state(
find.byKey(const ValueKey<String>(topRoute)),
find.byKey(const ValueKey<String?>(topRoute)),
);
expect(topState.widget.name, topRoute);
await tester.pump(const Duration(milliseconds: 150));
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pumpAndSettle();
expect(
tester.state(find.byKey(
const ValueKey<String>(bottomRoute),
const ValueKey<String?>(bottomRoute),
skipOffstage: false,
)),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pump(const Duration(milliseconds: 150));
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pumpAndSettle();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(find.byKey(const ValueKey<String>(topRoute)), findsNothing);
expect(find.byKey(const ValueKey<String?>(topRoute)), findsNothing);
},
);
@ -1168,21 +1168,21 @@ void main() {
Finder fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/')),
of: find.byKey(const ValueKey<String?>('/')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
expect(tester.widget<Container>(fillContainerFinder).color,
defaultFillColor);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pumpAndSettle();
fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/a')),
of: find.byKey(const ValueKey<String?>('/a')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
@ -1207,20 +1207,20 @@ void main() {
Finder fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/')),
of: find.byKey(const ValueKey<String?>('/')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
expect(tester.widget<Container>(fillContainerFinder).color, Colors.green);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pumpAndSettle();
fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/a')),
of: find.byKey(const ValueKey<String?>('/a')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
@ -1340,7 +1340,7 @@ void main() {
expect(_getOpacity(bottomRoute, tester), 1.0);
expect(find.text(topRoute), findsNothing);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pump();
@ -1413,7 +1413,7 @@ void main() {
),
);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pumpAndSettle();
expect(find.text(topRoute), findsOneWidget);
@ -1421,7 +1421,7 @@ void main() {
expect(_getOpacity(topRoute, tester), 1.0);
expect(find.text(bottomRoute), findsNothing);
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
// Top route is full size and fully visible.
@ -1498,7 +1498,7 @@ void main() {
expect(find.text(bottomRoute), findsOneWidget);
expect(find.text(topRoute), findsNothing);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
// Jump to halfway point of transition.
@ -1520,7 +1520,7 @@ void main() {
expect(halfwayTopOpacity, lessThan(1.0));
// Interrupt the transition with a pop.
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
// Nothing should change.
@ -1571,7 +1571,7 @@ void main() {
expect(find.text(bottomRoute), findsOneWidget);
expect(find.text(topRoute), findsNothing);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
// Jump to halfway point of transition.
@ -1606,82 +1606,82 @@ void main() {
transitionType: SharedAxisTransitionType.scaled,
contentBuilder: (RouteSettings settings) {
return _StatefulTestWidget(
key: ValueKey<String>(settings.name),
name: settings.name,
key: ValueKey<String?>(settings.name),
name: settings.name!,
);
},
),
);
final _StatefulTestWidgetState bottomState = tester.state(
find.byKey(const ValueKey<String>(bottomRoute)),
find.byKey(const ValueKey<String?>(bottomRoute)),
);
expect(bottomState.widget.name, bottomRoute);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pump();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
final _StatefulTestWidgetState topState = tester.state(
find.byKey(const ValueKey<String>(topRoute)),
find.byKey(const ValueKey<String?>(topRoute)),
);
expect(topState.widget.name, topRoute);
await tester.pump(const Duration(milliseconds: 150));
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pumpAndSettle();
expect(
tester.state(find.byKey(
const ValueKey<String>(bottomRoute),
const ValueKey<String?>(bottomRoute),
skipOffstage: false,
)),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pump(const Duration(milliseconds: 150));
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(
tester.state(find.byKey(const ValueKey<String>(topRoute))),
tester.state(find.byKey(const ValueKey<String?>(topRoute))),
topState,
);
await tester.pumpAndSettle();
expect(
tester.state(find.byKey(const ValueKey<String>(bottomRoute))),
tester.state(find.byKey(const ValueKey<String?>(bottomRoute))),
bottomState,
);
expect(find.byKey(const ValueKey<String>(topRoute)), findsNothing);
expect(find.byKey(const ValueKey<String?>(topRoute)), findsNothing);
},
);
@ -1704,21 +1704,21 @@ void main() {
Finder fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/')),
of: find.byKey(const ValueKey<String?>('/')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
expect(tester.widget<Container>(fillContainerFinder).color,
defaultFillColor);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pumpAndSettle();
fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/a')),
of: find.byKey(const ValueKey<String?>('/a')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
@ -1743,20 +1743,20 @@ void main() {
Finder fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/')),
of: find.byKey(const ValueKey<String?>('/')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
expect(tester.widget<Container>(fillContainerFinder).color, Colors.green);
navigator.currentState.pushNamed(topRoute);
navigator.currentState!.pushNamed(topRoute);
await tester.pump();
await tester.pumpAndSettle();
fillContainerFinder = find
.ancestor(
matching: find.byType(Container),
of: find.byKey(const ValueKey<String>('/a')),
of: find.byKey(const ValueKey<String?>('/a')),
)
.last;
expect(fillContainerFinder, findsOneWidget);
@ -1833,22 +1833,22 @@ void main() {
double _getOpacity(String key, WidgetTester tester) {
final Finder finder = find.ancestor(
of: find.byKey(ValueKey<String>(key)),
of: find.byKey(ValueKey<String?>(key)),
matching: find.byType(FadeTransition),
);
return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
final FadeTransition transition = widget;
final FadeTransition transition = widget as FadeTransition;
return a * transition.opacity.value;
});
}
double _getTranslationOffset(
double? _getTranslationOffset(
String key,
WidgetTester tester,
SharedAxisTransitionType transitionType,
) {
final Finder finder = find.ancestor(
of: find.byKey(ValueKey<String>(key)),
of: find.byKey(ValueKey<String?>(key)),
matching: find.byType(Transform),
);
@ -1856,56 +1856,52 @@ double _getTranslationOffset(
case SharedAxisTransitionType.horizontal:
return tester.widgetList<Transform>(finder).fold<double>(0.0,
(double a, Widget widget) {
final Transform transition = widget;
final Transform transition = widget as Transform;
final Vector3 translation = transition.transform.getTranslation();
return a + translation.x;
});
break;
case SharedAxisTransitionType.vertical:
return tester.widgetList<Transform>(finder).fold<double>(0.0,
(double a, Widget widget) {
final Transform transition = widget;
final Transform transition = widget as Transform;
final Vector3 translation = transition.transform.getTranslation();
return a + translation.y;
});
break;
case SharedAxisTransitionType.scaled:
// SharedAxisTransitionType.scaled should not return a translation
// offset.
return null;
break;
}
return null; // unreachable
}
double _getScale(String key, WidgetTester tester) {
final Finder finder = find.ancestor(
of: find.byKey(ValueKey<String>(key)),
of: find.byKey(ValueKey<String?>(key)),
matching: find.byType(ScaleTransition),
);
return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
final ScaleTransition transition = widget;
final ScaleTransition transition = widget as ScaleTransition;
return a * transition.scale.value;
});
}
class _TestWidget extends StatelessWidget {
const _TestWidget({
this.navigatorKey,
required this.navigatorKey,
this.contentBuilder,
this.transitionType,
required this.transitionType,
this.fillColor,
});
final Key navigatorKey;
final _ContentBuilder contentBuilder;
final _ContentBuilder? contentBuilder;
final SharedAxisTransitionType transitionType;
final Color fillColor;
final Color? fillColor;
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: navigatorKey,
navigatorKey: navigatorKey as GlobalKey<NavigatorState>?,
theme: ThemeData(
platform: TargetPlatform.android,
pageTransitionsTheme: PageTransitionsTheme(
@ -1922,11 +1918,11 @@ class _TestWidget extends StatelessWidget {
settings: settings,
builder: (BuildContext context) {
return contentBuilder != null
? contentBuilder(settings)
? contentBuilder!(settings)
: Container(
child: Center(
key: ValueKey<String>(settings.name),
child: Text(settings.name),
key: ValueKey<String?>(settings.name),
child: Text(settings.name!),
),
);
},
@ -1937,7 +1933,7 @@ class _TestWidget extends StatelessWidget {
}
class _StatefulTestWidget extends StatefulWidget {
const _StatefulTestWidget({Key key, this.name}) : super(key: key);
const _StatefulTestWidget({Key? key, required this.name}) : super(key: key);
final String name;

View File

@ -15,7 +15,7 @@ function check_publish() {
for package_name in "$@"; do
local dir="$REPO_DIR/packages/$package_name"
echo "Checking that $package_name can be published."
if (cd "$dir" && pub publish --dry-run > /dev/null); then
if (cd "$dir" && flutter pub publish --dry-run > /dev/null); then
echo "Package $package_name is able to be published."
else
error "Unable to publish $package_name"