mirror of
https://github.com/flutter/packages.git
synced 2025-06-29 06:06:59 +08:00
Merge NNBD branch into master (#270)
This commit is contained in:

committed by
GitHub

parent
1c7d23bdbe
commit
f3e92fded0
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -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),
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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++) {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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"
|
||||
@ -36,4 +36,4 @@ check_changed_packages
|
||||
|
||||
if [[ "${#CHANGED_PACKAGE_LIST[@]}" != 0 ]]; then
|
||||
check_publish "${CHANGED_PACKAGE_LIST[@]}"
|
||||
fi
|
||||
fi
|
||||
|
Reference in New Issue
Block a user