diff --git a/dev/integration_tests/flutter_gallery/test/demo/cupertino/cupertino_navigation_demo_test.dart b/dev/integration_tests/flutter_gallery/test/demo/cupertino/cupertino_navigation_demo_test.dart index 713aa3502e..bdec31f114 100644 --- a/dev/integration_tests/flutter_gallery/test/demo/cupertino/cupertino_navigation_demo_test.dart +++ b/dev/integration_tests/flutter_gallery/test/demo/cupertino/cupertino_navigation_demo_test.dart @@ -32,7 +32,7 @@ void main() { // Tap some row to go to the next page. await tester.tap(find.text('Buy this cool color').first); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); await expectLater( find.byType(CupertinoNavigationDemo), diff --git a/packages/flutter/lib/src/animation/curves.dart b/packages/flutter/lib/src/animation/curves.dart index 95610df181..fa75eadd96 100644 --- a/packages/flutter/lib/src/animation/curves.dart +++ b/packages/flutter/lib/src/animation/curves.dart @@ -6,6 +6,7 @@ import 'dart:math' as math; import 'dart:ui'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; export 'dart:ui' show Offset; @@ -1381,6 +1382,26 @@ abstract final class Curves { /// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_fast_linear_to_slow_ease_in.mp4} static const Cubic fastLinearToSlowEaseIn = Cubic(0.18, 1.0, 0.04, 1.0); + /// A curve that starts slowly, speeds up very quickly, and then ends slowly. + /// + /// This curve is used by default to animate page transitions used by + /// [CupertinoPageRoute]. + /// + /// It has been derived from plots of native iOS 16.3 + /// animation frames on iPhone 14 Pro Max. + /// Specifically, transition animation positions were measured + /// every frame and plotted against time. Then, a cubic curve was + /// strictly fit to the measured data points. + /// + /// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_fast_ease_in_to_slow_ease_out.mp4} + static const ThreePointCubic fastEaseInToSlowEaseOut = ThreePointCubic( + Offset(0.056, 0.024), + Offset(0.108, 0.3085), + Offset(0.198, 0.541), + Offset(0.3655, 1.0), + Offset(0.5465, 0.989), + ); + /// A cubic animation curve that speeds up quickly and ends slowly. /// /// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_ease.mp4} diff --git a/packages/flutter/lib/src/cupertino/route.dart b/packages/flutter/lib/src/cupertino/route.dart index d5722addea..e0d6a83933 100644 --- a/packages/flutter/lib/src/cupertino/route.dart +++ b/packages/flutter/lib/src/cupertino/route.dart @@ -136,7 +136,7 @@ mixin CupertinoRouteTransitionMixin on PageRoute { @override // A relatively rigorous eyeball estimation. - Duration get transitionDuration => const Duration(milliseconds: 400); + Duration get transitionDuration => const Duration(milliseconds: 500); @override Color? get barrierColor => fullscreenDialog ? null : _kCupertinoPageTransitionBarrierColor; @@ -457,15 +457,9 @@ class CupertinoPageTransition extends StatelessWidget { (linearTransition ? primaryRouteAnimation : CurvedAnimation( - // The curves below have been rigorously derived from plots of native - // iOS animation frames. Specifically, a video was taken of a page - // transition animation and the distance in each frame that the page - // moved was measured. A best fit bezier curve was the fitted to the - // point set, which is linearToEaseIn. Conversely, easeInToLinear is the - // reflection over the origin of linearToEaseIn. parent: primaryRouteAnimation, - curve: Curves.linearToEaseOut, - reverseCurve: Curves.easeInToLinear, + curve: Curves.fastEaseInToSlowEaseOut, + reverseCurve: Curves.fastEaseInToSlowEaseOut.flipped, ) ).drive(_kRightMiddleTween), _secondaryPositionAnimation = diff --git a/packages/flutter/test/cupertino/nav_bar_test.dart b/packages/flutter/test/cupertino/nav_bar_test.dart index 5bb009eb7f..9b7532afd0 100644 --- a/packages/flutter/test/cupertino/nav_bar_test.dart +++ b/packages/flutter/test/cupertino/nav_bar_test.dart @@ -53,7 +53,7 @@ void main() { )); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); // Expect the middle of the title to be exactly in the middle of the screen. expect(tester.getCenter(find.text('Page 2')).dx, 400.0); @@ -673,7 +673,7 @@ void main() { )); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.byType(CupertinoButton), findsOneWidget); expect(find.text(String.fromCharCode(CupertinoIcons.back.codePoint)), findsOneWidget); @@ -688,7 +688,7 @@ void main() { )); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.widgetWithText(CupertinoButton, 'Close'), findsOneWidget); @@ -696,14 +696,14 @@ void main() { await tester.tap(find.text('Close')); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.text('Page 2'), findsOneWidget); await tester.tap(find.text(String.fromCharCode(CupertinoIcons.back.codePoint))); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.text('Home page'), findsOneWidget); }); @@ -1157,7 +1157,7 @@ void main() { ); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); tester.state(find.byType(Navigator)).push( CupertinoPageRoute( @@ -1176,11 +1176,11 @@ void main() { ); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); await tester.tap(find.byType(CupertinoNavigationBarBackButton)); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); // The second page is still on top and didn't pop. expect(find.text('A Phone'), findsOneWidget); @@ -1406,13 +1406,13 @@ void main() { ); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.text('Page 1'), findsNothing); expect(find.text('Page 2'), findsOneWidget); await tester.tap(find.text(String.fromCharCode(CupertinoIcons.back.codePoint))); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.text('Page 1'), findsOneWidget); expect(find.text('Page 2'), findsNothing); }); diff --git a/packages/flutter/test/cupertino/nav_bar_transition_test.dart b/packages/flutter/test/cupertino/nav_bar_transition_test.dart index fb88075348..b8d3791c80 100644 --- a/packages/flutter/test/cupertino/nav_bar_transition_test.dart +++ b/packages/flutter/test/cupertino/nav_bar_transition_test.dart @@ -51,7 +51,7 @@ Future startTransitionBetween( )); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); tester .state(find.byType(Navigator)) @@ -150,11 +150,11 @@ void main() { // place. expect( tester.getTopLeft(flying(tester, find.text('Page 1')).first), - const Offset(337.1953125, 13.5), + const Offset(342.33420100808144, 13.5), ); expect( tester.getTopLeft(flying(tester, find.text('Page 1')).last), - const Offset(337.1953125, 13.5), + const Offset(342.33420100808144, 13.5), ); }); @@ -171,11 +171,11 @@ void main() { // Same as LTR but more to the right now. expect( tester.getTopLeft(flying(tester, find.text('Page 1')).first), - const Offset(362.8046875, 13.5), + const Offset(357.66579899191856, 13.5), ); expect( tester.getTopLeft(flying(tester, find.text('Page 1')).last), - const Offset(362.8046875, 13.5), + const Offset(357.66579899191856, 13.5), ); }); @@ -209,18 +209,18 @@ void main() { // The transition's stack is ordered. The bottom middle is inserted first. final RenderParagraph bottomMiddle = tester.renderObject(flying(tester, find.text('Page 1')).first); - expect(bottomMiddle.text.style!.color, const Color(0xff00050a)); + expect(bottomMiddle.text.style!.color, const Color(0xff000306)); expect(bottomMiddle.text.style!.fontWeight, FontWeight.w600); expect(bottomMiddle.text.style!.fontFamily, '.SF Pro Text'); expect(bottomMiddle.text.style!.letterSpacing, -0.41); - checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.9004602432250977); + checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.9404401779174805); // The top back label is styled exactly the same way. But the opacity tweens // are flipped. final RenderParagraph topBackLabel = tester.renderObject(flying(tester, find.text('Page 1')).last); - expect(topBackLabel.text.style!.color, const Color(0xff00050a)); + expect(topBackLabel.text.style!.color, const Color(0xff000306)); expect(topBackLabel.text.style!.fontWeight, FontWeight.w600); expect(topBackLabel.text.style!.fontFamily, '.SF Pro Text'); expect(topBackLabel.text.style!.letterSpacing, -0.41); @@ -229,19 +229,19 @@ void main() { // Move animation further a bit. await tester.pump(const Duration(milliseconds: 200)); - expect(bottomMiddle.text.style!.color, const Color(0xff006de4)); + expect(bottomMiddle.text.style!.color, const Color(0xff005ec5)); expect(bottomMiddle.text.style!.fontWeight, FontWeight.w400); expect(bottomMiddle.text.style!.fontFamily, '.SF Pro Text'); expect(bottomMiddle.text.style!.letterSpacing, -0.41); checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.0); - expect(topBackLabel.text.style!.color, const Color(0xff006de4)); + expect(topBackLabel.text.style!.color, const Color(0xff005ec5)); expect(topBackLabel.text.style!.fontWeight, FontWeight.w400); expect(topBackLabel.text.style!.fontFamily, '.SF Pro Text'); expect(topBackLabel.text.style!.letterSpacing, -0.41); - checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.7630139589309692); + checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.5292819738388062); }); testWidgets('Font transitions respect themes', (WidgetTester tester) async { @@ -257,18 +257,18 @@ void main() { // The transition's stack is ordered. The bottom middle is inserted first. final RenderParagraph bottomMiddle = tester.renderObject(flying(tester, find.text('Page 1')).first); - expect(bottomMiddle.text.style!.color, const Color(0xFFF4F9FF)); + expect(bottomMiddle.text.style!.color, const Color(0xfff8fbff)); expect(bottomMiddle.text.style!.fontWeight, FontWeight.w600); expect(bottomMiddle.text.style!.fontFamily, '.SF Pro Text'); expect(bottomMiddle.text.style!.letterSpacing, -0.41); - checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.9004602432250977); + checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.9404401779174805); // The top back label is styled exactly the same way. But the opacity tweens // are flipped. final RenderParagraph topBackLabel = tester.renderObject(flying(tester, find.text('Page 1')).last); - expect(topBackLabel.text.style!.color, const Color(0xFFF4F9FF)); + expect(topBackLabel.text.style!.color, const Color(0xfff8fbff)); expect(topBackLabel.text.style!.fontWeight, FontWeight.w600); expect(topBackLabel.text.style!.fontFamily, '.SF Pro Text'); expect(topBackLabel.text.style!.letterSpacing, -0.41); @@ -277,19 +277,19 @@ void main() { // Move animation further a bit. await tester.pump(const Duration(milliseconds: 200)); - expect(bottomMiddle.text.style!.color, const Color(0xFF2390FF)); + expect(bottomMiddle.text.style!.color, const Color(0xff409fff)); expect(bottomMiddle.text.style!.fontWeight, FontWeight.w400); expect(bottomMiddle.text.style!.fontFamily, '.SF Pro Text'); expect(bottomMiddle.text.style!.letterSpacing, -0.41); checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.0); - expect(topBackLabel.text.style!.color, const Color(0xFF2390FF)); + expect(topBackLabel.text.style!.color, const Color(0xff409fff)); expect(topBackLabel.text.style!.fontWeight, FontWeight.w400); expect(topBackLabel.text.style!.fontFamily, '.SF Pro Text'); expect(topBackLabel.text.style!.letterSpacing, -0.41); - checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.7630139589309692); + checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.5292819738388062); }); testWidgets('Fullscreen dialogs do not create heroes', (WidgetTester tester) async { @@ -360,20 +360,20 @@ void main() { // The transition's stack is ordered. The bottom middle is inserted first. final RenderParagraph bottomMiddle = tester.renderObject(flying(tester, find.text('Page 1')).first); - expect(bottomMiddle.text.style!.color, const Color(0xff00050a)); + expect(bottomMiddle.text.style!.color, const Color(0xff000306)); expect( tester.getTopLeft(flying(tester, find.text('Page 1')).first), - const Offset(337.1953125, 13.5), + const Offset(342.33420100808144, 13.5), ); // The top back label is styled exactly the same way. But the opacity tweens // are flipped. final RenderParagraph topBackLabel = tester.renderObject(flying(tester, find.text('Page 1')).last); - expect(topBackLabel.text.style!.color, const Color(0xff00050a)); + expect(topBackLabel.text.style!.color, const Color(0xff000306)); expect( tester.getTopLeft(flying(tester, find.text('Page 1')).last), - const Offset(337.1953125, 13.5), + const Offset(342.33420100808144, 13.5), ); } @@ -405,20 +405,20 @@ void main() { // The transition's stack is ordered. The bottom middle is inserted first. final RenderParagraph bottomMiddle = tester.renderObject(flying(tester, find.text('Page 1')).first); - expect(bottomMiddle.text.style!.color, const Color(0xff00050a)); + expect(bottomMiddle.text.style!.color, const Color(0xff000306)); expect( tester.getTopLeft(flying(tester, find.text('Page 1')).first), - const Offset(362.8046875, 13.5), + const Offset(357.66579899191856, 13.5), ); // The top back label is styled exactly the same way. But the opacity tweens // are flipped. final RenderParagraph topBackLabel = tester.renderObject(flying(tester, find.text('Page 1')).last); - expect(topBackLabel.text.style!.color, const Color(0xff00050a)); + expect(topBackLabel.text.style!.color, const Color(0xff000306)); expect( tester.getTopLeft(flying(tester, find.text('Page 1')).last), - const Offset(362.8046875, 13.5), + const Offset(357.66579899191856, 13.5), ); } @@ -555,19 +555,19 @@ void main() { ); await tester.pump(const Duration(milliseconds: 50)); - checkBackgroundBoxHeight(tester, 46.234375); + checkBackgroundBoxHeight(tester, 45.3376561999321); await tester.pump(const Duration(milliseconds: 50)); - checkBackgroundBoxHeight(tester, 56.3232741355896); + checkBackgroundBoxHeight(tester, 51.012951374053955); await tester.pump(const Duration(milliseconds: 50)); - checkBackgroundBoxHeight(tester, 73.04067611694336); + checkBackgroundBoxHeight(tester, 63.06760931015015); + + await tester.pump(const Duration(milliseconds: 50)); + checkBackgroundBoxHeight(tester, 75.89544230699539); await tester.pump(const Duration(milliseconds: 50)); checkBackgroundBoxHeight(tester, 84.33018499612808); - - await tester.pump(const Duration(milliseconds: 50)); - checkBackgroundBoxHeight(tester, 90.53337162733078); }); testWidgets('Large transition box shrinks to standard nav bar size', (WidgetTester tester) async { @@ -579,19 +579,19 @@ void main() { ); await tester.pump(const Duration(milliseconds: 50)); - checkBackgroundBoxHeight(tester, 93.765625); + checkBackgroundBoxHeight(tester, 94.6623438000679); await tester.pump(const Duration(milliseconds: 50)); - checkBackgroundBoxHeight(tester, 83.6767258644104); + checkBackgroundBoxHeight(tester, 88.98704862594604); await tester.pump(const Duration(milliseconds: 50)); - checkBackgroundBoxHeight(tester, 66.95932388305664); + checkBackgroundBoxHeight(tester, 76.93239068984985); + + await tester.pump(const Duration(milliseconds: 50)); + checkBackgroundBoxHeight(tester, 64.10455769300461); await tester.pump(const Duration(milliseconds: 50)); checkBackgroundBoxHeight(tester, 55.66981500387192); - - await tester.pump(const Duration(milliseconds: 50)); - checkBackgroundBoxHeight(tester, 49.46662837266922); }); testWidgets('Hero flight removed at the end of page transition', (WidgetTester tester) async { @@ -716,9 +716,9 @@ void main() { ); // Come in from the right and fade in. checkOpacity(tester, backChevron, 0.0); - expect(tester.getTopLeft(backChevron), const Offset(86.734375, 7.0)); + expect(tester.getTopLeft(backChevron), const Offset(88.04496401548386, 7.0)); - await tester.pump(const Duration(milliseconds: 150)); + await tester.pump(const Duration(milliseconds: 200)); checkOpacity(tester, backChevron, 0.09497911669313908); expect(tester.getTopLeft(backChevron), const Offset(31.055883467197418, 7.0)); }); @@ -758,10 +758,10 @@ void main() { checkOpacity(tester, backChevron, 0.0); expect( tester.getTopRight(backChevron), - const Offset(687.265625, 7.0), + const Offset(685.9550359845161, 7.0), ); - await tester.pump(const Duration(milliseconds: 150)); + await tester.pump(const Duration(milliseconds: 200)); checkOpacity(tester, backChevron, 0.09497911669313908); expect( tester.getTopRight(backChevron), @@ -781,13 +781,13 @@ void main() { findsNWidgets(2), ); - checkOpacity(tester, backChevrons.first, 0.8833301812410355); + checkOpacity(tester, backChevrons.first, 0.9280824661254883); checkOpacity(tester, backChevrons.last, 0.0); // Both overlap at the same place. expect(tester.getTopLeft(backChevrons.first), const Offset(14.0, 7.0)); expect(tester.getTopLeft(backChevrons.last), const Offset(14.0, 7.0)); - await tester.pump(const Duration(milliseconds: 150)); + await tester.pump(const Duration(milliseconds: 200)); checkOpacity(tester, backChevrons.first, 0.0); checkOpacity(tester, backChevrons.last, 0.4604858811944723); // Still in the same place. @@ -810,7 +810,7 @@ void main() { // There's just 1 in flight because there's no back label on the top page. expect(flying(tester, find.text('Page 1')), findsOneWidget); - checkOpacity(tester, flying(tester, find.text('Page 1')), 0.9004602432250977); + checkOpacity(tester, flying(tester, find.text('Page 1')), 0.9404401779174805); // The middle widget doesn't move. expect( @@ -818,7 +818,7 @@ void main() { const Offset(400.0, 22.0), ); - await tester.pump(const Duration(milliseconds: 150)); + await tester.pump(const Duration(milliseconds: 200)); checkOpacity(tester, flying(tester, find.text('Page 1')), 0.0); expect( tester.getCenter(flying(tester, find.text('Page 1'))), @@ -838,7 +838,7 @@ void main() { expect(flying(tester, find.text('custom')), findsOneWidget); - checkOpacity(tester, flying(tester, find.text('custom')), 0.828093871474266); + checkOpacity(tester, flying(tester, find.text('custom')), 0.8948725312948227); expect( tester.getTopLeft(flying(tester, find.text('custom'))), const Offset(16.0, 0.0), @@ -864,7 +864,7 @@ void main() { expect(flying(tester, find.text('custom')), findsOneWidget); - checkOpacity(tester, flying(tester, find.text('custom')), 0.8833301812410355); + checkOpacity(tester, flying(tester, find.text('custom')), 0.9280824661254883); expect( tester.getTopLeft(flying(tester, find.text('custom'))), const Offset(684.0, 13.5), @@ -900,13 +900,13 @@ void main() { expect(flying(tester, find.text('Page 1')), findsOneWidget); // Back label fades out faster. - checkOpacity(tester, flying(tester, find.text('Page 1')), 0.6697911769151688); + checkOpacity(tester, flying(tester, find.text('Page 1')), 0.7952219992876053); expect( tester.getTopLeft(flying(tester, find.text('Page 1'))), - const Offset(34.8125, 13.5), + const Offset(41.71033692359924, 13.5), ); - await tester.pump(const Duration(milliseconds: 150)); + await tester.pump(const Duration(milliseconds: 200)); checkOpacity(tester, flying(tester, find.text('Page 1')), 0.0); expect( tester.getTopLeft(flying(tester, find.text('Page 1'))), @@ -937,13 +937,13 @@ void main() { expect(flying(tester, find.text('Page 1')), findsOneWidget); // Back label fades out faster. - checkOpacity(tester, flying(tester, find.text('Page 1')), 0.6697911769151688); + checkOpacity(tester, flying(tester, find.text('Page 1')), 0.7952219992876053); expect( tester.getTopRight(flying(tester, find.text('Page 1'))), - const Offset(765.1875, 13.5), + const Offset(758.2896630764008, 13.5), ); - await tester.pump(const Duration(milliseconds: 150)); + await tester.pump(const Duration(milliseconds: 200)); checkOpacity(tester, flying(tester, find.text('Page 1')), 0.0); expect( tester.getTopRight(flying(tester, find.text('Page 1'))), @@ -966,18 +966,18 @@ void main() { // bottom back label fading in. expect(flying(tester, find.text('Page 1')), findsNWidgets(2)); - checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.8833301812410355); + checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.9280824661254883); checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.0); expect( tester.getTopLeft(flying(tester, find.text('Page 1')).first), - const Offset(17.546875, 52.39453125), + const Offset(16.926069676876068, 52.73951627314091), ); expect( tester.getTopLeft(flying(tester, find.text('Page 1')).last), - const Offset(17.546875, 52.39453125), + const Offset(16.926069676876068, 52.73951627314091), ); - await tester.pump(const Duration(milliseconds: 150)); + await tester.pump(const Duration(milliseconds: 200)); checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.0); checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.4604858811944723); expect( @@ -1004,18 +1004,18 @@ void main() { // Automatically changed to the word 'Back' in the back label. expect(flying(tester, find.text('Back')), findsOneWidget); - checkOpacity(tester, flying(tester, find.text('A title too long to fit')), 0.8833301812410355); + checkOpacity(tester, flying(tester, find.text('A title too long to fit')), 0.9280824661254883); checkOpacity(tester, flying(tester, find.text('Back')), 0.0); expect( tester.getTopLeft(flying(tester, find.text('A title too long to fit'))), - const Offset(17.546875, 52.39453125), + const Offset(16.926069676876068, 52.73951627314091), ); expect( tester.getTopLeft(flying(tester, find.text('Back'))), - const Offset(17.546875, 52.39453125), + const Offset(16.926069676876068, 52.73951627314091), ); - await tester.pump(const Duration(milliseconds: 150)); + await tester.pump(const Duration(milliseconds: 200)); checkOpacity(tester, flying(tester, find.text('A title too long to fit')), 0.0); checkOpacity(tester, flying(tester, find.text('Back')), 0.4604858811944723); expect( @@ -1041,30 +1041,30 @@ void main() { // The transition's stack is ordered. The bottom large title is inserted first. final RenderParagraph bottomLargeTitle = tester.renderObject(flying(tester, find.text('Page 1')).first); - expect(bottomLargeTitle.text.style!.color, const Color(0xff00050a)); + expect(bottomLargeTitle.text.style!.color, const Color(0xff000306)); expect(bottomLargeTitle.text.style!.fontWeight, FontWeight.w700); expect(bottomLargeTitle.text.style!.fontFamily, '.SF Pro Display'); - expect(bottomLargeTitle.text.style!.letterSpacing, moreOrLessEquals(0.374765625)); + expect(bottomLargeTitle.text.style!.letterSpacing, moreOrLessEquals(0.38890619069337845)); // The top back label is styled exactly the same way. final RenderParagraph topBackLabel = tester.renderObject(flying(tester, find.text('Page 1')).last); - expect(topBackLabel.text.style!.color, const Color(0xff00050a)); + expect(topBackLabel.text.style!.color, const Color(0xff000306)); expect(topBackLabel.text.style!.fontWeight, FontWeight.w700); expect(topBackLabel.text.style!.fontFamily, '.SF Pro Display'); - expect(topBackLabel.text.style!.letterSpacing, moreOrLessEquals(0.374765625)); + expect(topBackLabel.text.style!.letterSpacing, moreOrLessEquals(0.38890619069337845)); // Move animation further a bit. await tester.pump(const Duration(milliseconds: 200)); - expect(bottomLargeTitle.text.style!.color, const Color(0xff006de4)); - expect(bottomLargeTitle.text.style!.fontWeight, FontWeight.w400); + expect(bottomLargeTitle.text.style!.color, const Color(0xff005ec5)); + expect(bottomLargeTitle.text.style!.fontWeight, FontWeight.w500); expect(bottomLargeTitle.text.style!.fontFamily, '.SF Pro Text'); - expect(bottomLargeTitle.text.style!.letterSpacing, moreOrLessEquals(-0.32379547566175454)); + expect(bottomLargeTitle.text.style!.letterSpacing, moreOrLessEquals(-0.2259759941697121)); - expect(topBackLabel.text.style!.color, const Color(0xff006de4)); - expect(topBackLabel.text.style!.fontWeight, FontWeight.w400); + expect(topBackLabel.text.style!.color, const Color(0xff005ec5)); + expect(topBackLabel.text.style!.fontWeight, FontWeight.w500); expect(topBackLabel.text.style!.fontFamily, '.SF Pro Text'); - expect(topBackLabel.text.style!.letterSpacing, moreOrLessEquals(-0.32379547566175454)); + expect(topBackLabel.text.style!.letterSpacing, moreOrLessEquals(-0.2259759941697121)); }); testWidgets('Top middle fades in and slides in from the right', (WidgetTester tester) async { @@ -1080,15 +1080,15 @@ void main() { checkOpacity(tester, flying(tester, find.text('Page 2')), 0.0); expect( tester.getTopLeft(flying(tester, find.text('Page 2'))), - const Offset(732.8125, 13.5), + const Offset(739.7103369235992, 13.5), ); await tester.pump(const Duration(milliseconds: 150)); - checkOpacity(tester, flying(tester, find.text('Page 2')), 0.5555618554353714); + checkOpacity(tester, flying(tester, find.text('Page 2')), 0.29867843724787235); expect( tester.getTopLeft(flying(tester, find.text('Page 2'))), - const Offset(439.7678077220917, 13.5), + const Offset(504.65044379234314, 13.5), ); }); @@ -1130,15 +1130,15 @@ void main() { checkOpacity(tester, flying(tester, find.text('Page 2')), 0.0); expect( tester.getTopRight(flying(tester, find.text('Page 2'))), - const Offset(67.1875, 13.5), + const Offset(60.28966307640076, 13.5), ); await tester.pump(const Duration(milliseconds: 150)); - checkOpacity(tester, flying(tester, find.text('Page 2')), 0.5555618554353714); + checkOpacity(tester, flying(tester, find.text('Page 2')), 0.29867843724787235); expect( tester.getTopRight(flying(tester, find.text('Page 2'))), - const Offset(360.2321922779083, 13.5), + const Offset(295.34955620765686, 13.5), ); }); @@ -1156,15 +1156,15 @@ void main() { checkOpacity(tester, flying(tester, find.text('Page 2')), 0.0); expect( tester.getTopLeft(flying(tester, find.text('Page 2'))), - const Offset(781.625, 54.0), + const Offset(795.4206738471985, 54.0), ); await tester.pump(const Duration(milliseconds: 150)); - checkOpacity(tester, flying(tester, find.text('Page 2')), 0.5292819738388062); + checkOpacity(tester, flying(tester, find.text('Page 2')), 0.2601277381181717); expect( tester.getTopLeft(flying(tester, find.text('Page 2'))), - const Offset(195.53561544418335, 54.0), + const Offset(325.3008875846863, 54.0), ); }); @@ -1183,15 +1183,15 @@ void main() { checkOpacity(tester, flying(tester, find.text('Page 2')), 0.0); expect( tester.getTopRight(flying(tester, find.text('Page 2'))), - const Offset(18.375, 54.0), + const Offset(4.579326152801514, 54.0), ); await tester.pump(const Duration(milliseconds: 150)); - checkOpacity(tester, flying(tester, find.text('Page 2')), 0.5292819738388062); + checkOpacity(tester, flying(tester, find.text('Page 2')), 0.2601277381181717); expect( tester.getTopRight(flying(tester, find.text('Page 2'))), - const Offset(604.4643845558167, 54.0), + const Offset(474.6991124153137, 54.0), ); }); @@ -1248,10 +1248,10 @@ void main() { ); // Go to the next page. - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); // Start the gesture at the edge of the screen. - final TestGesture gesture = await tester.startGesture(const Offset(5.0, 200.0)); + final TestGesture gesture = await tester.startGesture(const Offset(5.0, 200.0)); // Trigger the swipe. await gesture.moveBy(const Offset(100.0, 0.0)); @@ -1310,7 +1310,7 @@ void main() { ); // Go to the next page. - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); // Start the gesture at the edge of the screen. final TestGesture gesture = await tester.startGesture(const Offset(5.0, 200.0)); diff --git a/packages/flutter/test/cupertino/page_test.dart b/packages/flutter/test/cupertino/page_test.dart index efc3322b48..5fcf65feb3 100644 --- a/packages/flutter/test/cupertino/page_test.dart +++ b/packages/flutter/test/cupertino/page_test.dart @@ -41,7 +41,7 @@ void main() { expect(widget2TopLeft.dx, greaterThan(widget1InitialTopLeft.dx)); // Will need to be changed if the animation curve or duration changes. - expect(widget1TransientTopLeft.dx, moreOrLessEquals(130, epsilon: 1.0)); + expect(widget1TransientTopLeft.dx, moreOrLessEquals(158, epsilon: 1.0)); await tester.pumpAndSettle(); @@ -66,7 +66,7 @@ void main() { expect(widget2TopLeft.dx, greaterThan(widget1InitialTopLeft.dx)); // Will need to be changed if the animation curve or duration changes. - expect(widget1TransientTopLeft.dx, moreOrLessEquals(249, epsilon: 1.0)); + expect(widget1TransientTopLeft.dx, moreOrLessEquals(220, epsilon: 1.0)); await tester.pumpAndSettle(); diff --git a/packages/flutter/test/cupertino/route_test.dart b/packages/flutter/test/cupertino/route_test.dart index 0c2dc3108e..804ef677a5 100644 --- a/packages/flutter/test/cupertino/route_test.dart +++ b/packages/flutter/test/cupertino/route_test.dart @@ -138,7 +138,7 @@ void main() { ); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); tester.state(find.byType(Navigator)).push( CupertinoPageRoute( @@ -153,7 +153,7 @@ void main() { ); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.widgetWithText(CupertinoNavigationBar, 'A Phone'), findsOneWidget); expect(tester.getCenter(find.text('A Phone')).dx, 400.0); @@ -415,65 +415,66 @@ void main() { // entire screen. await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(443.7, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(475.6, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(291.9, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(350.0, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(168.2, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(237.4, epsilon: 0.1)); + + await tester.pump(const Duration(milliseconds: 40)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(149.2, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(89.5, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(48.1, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(54.4, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(26.1, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(33.2, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(14.3, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(20.4, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(7.41, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(12.6, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(3.0, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(7.4, epsilon: 0.1)); - await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(0.0, epsilon: 0.1)); // Exit animation await tester.tap(find.text('Close')); await tester.pump(); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(156.3, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(411.03, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(308.1, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(484.35, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(431.7, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(530.67, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(510.4, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(557.61, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(551.8, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(573.88, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(573.8, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(583.86, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(585.6, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(590.26, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(592.6, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(594.58, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(596.9, epsilon: 0.1)); + expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(597.66, epsilon: 0.1)); await tester.pump(const Duration(milliseconds: 40)); expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(600.0, epsilon: 0.1)); @@ -520,41 +521,41 @@ void main() { // entire screen. await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-70.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-55.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-137.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-111.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-192.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-161.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-227.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-200.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-246.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-226.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-255.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-242.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-260.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-251.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-264.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-257.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-266.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-261.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-267.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-263.0, epsilon: 1.0)); // Exit animation await tester.tap(find.text('Close')); await tester.pump(); await tester.pump(const Duration(milliseconds: 40)); - expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-198.0, epsilon: 1.0)); + expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-83.0, epsilon: 1.0)); await tester.pump(const Duration(milliseconds: 360)); expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-0.0, epsilon: 1.0)); @@ -673,40 +674,40 @@ void main() { ); tester.state(find.byType(Navigator)).push(route2); - // The whole transition is 400ms based on CupertinoPageRoute.transitionDuration. + // The whole transition is 500ms based on CupertinoPageRoute.transitionDuration. // Break it up into small chunks. await tester.pump(); await tester.pump(const Duration(milliseconds: 50)); - expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-87, epsilon: 1)); - expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(537, epsilon: 1)); + expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-69, epsilon: 1)); + expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(609, epsilon: 1)); await tester.pump(const Duration(milliseconds: 50)); - expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-166, epsilon: 1)); - expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(301, epsilon: 1)); + expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-136, epsilon: 1)); + expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(362, epsilon: 1)); await tester.pump(const Duration(milliseconds: 50)); // Translation slows down as time goes on. - expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-220, epsilon: 1)); - expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(141, epsilon: 1)); + expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-191, epsilon: 1)); + expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(192, epsilon: 1)); // Finish the rest of the animation - await tester.pump(const Duration(milliseconds: 250)); + await tester.pump(const Duration(milliseconds: 350)); tester.state(find.byType(Navigator)).pop(); await tester.pump(); await tester.pump(const Duration(milliseconds: 50)); - expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-179, epsilon: 1)); - expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(262, epsilon: 1)); + expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-197, epsilon: 1)); + expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(190, epsilon: 1)); await tester.pump(const Duration(milliseconds: 50)); - expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-100, epsilon: 1)); - expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(499, epsilon: 1)); + expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-129, epsilon: 1)); + expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(437, epsilon: 1)); await tester.pump(const Duration(milliseconds: 50)); // Translation slows down as time goes on. - expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-47, epsilon: 1)); - expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(659, epsilon: 1)); + expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-74, epsilon: 1)); + expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(607, epsilon: 1)); }); testWidgets('Dragged pop gesture is linear', (WidgetTester tester) async { @@ -1060,7 +1061,7 @@ void main() { expect(box, paintsShadowRect(dx: 468, color: const Color(0x01000000))); expect(box, paintsShadowRect(dx: 458, color: const Color(0x00000000))); - await tester.pump(const Duration(milliseconds: 250)); + await tester.pump(const Duration(milliseconds: 150)); // At the end of the animation, the shadow approaches full transparency expect(box, paintsShadowRect(dx: 794, color: const Color(0x01000000))); diff --git a/packages/flutter/test/cupertino/scaffold_test.dart b/packages/flutter/test/cupertino/scaffold_test.dart index 463884b753..41b40c07b1 100644 --- a/packages/flutter/test/cupertino/scaffold_test.dart +++ b/packages/flutter/test/cupertino/scaffold_test.dart @@ -364,7 +364,7 @@ void main() { // Navigate in tab 2. await tester.tap(find.text('Next')); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.text('Page 2 of tab 2'), isOnstage); expect(find.text('Page 1 of tab 1', skipOffstage: false), isOffstage); @@ -379,7 +379,7 @@ void main() { // Navigate in tab 1. await tester.tap(find.text('Next')); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.text('Page 2 of tab 1'), isOnstage); expect(find.text('Page 2 of tab 2', skipOffstage: false), isOffstage); @@ -393,7 +393,7 @@ void main() { // Pop in tab 2 await tester.tap(find.text('Back')); await tester.pump(); - await tester.pump(const Duration(milliseconds: 500)); + await tester.pump(const Duration(milliseconds: 600)); expect(find.text('Page 1 of tab 2'), isOnstage); expect(find.text('Page 2 of tab 1', skipOffstage: false), isOffstage);