Unverified Commit 302c0877 authored by ivirtex's avatar ivirtex Committed by GitHub

Update `CupertinoPageRoute` transition animation curves (#122275)

Update `CupertinoPageRoute` transition animation curves
parent 84078c85
......@@ -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),
......
......@@ -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}
......
......@@ -136,7 +136,7 @@ mixin CupertinoRouteTransitionMixin<T> on PageRoute<T> {
@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 =
......
......@@ -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<NavigatorState>(find.byType(Navigator)).push(
CupertinoPageRoute<void>(
......@@ -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);
});
......
......@@ -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();
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment