-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Create new page transition for M3 #158881
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
14ab1a1 to
d382146
Compare
MitchellGoodwin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really good on a first pass! I'm wondering about migrating to this new transition being the default though. I think some of the Google testing might be difficult to adjust in one go.
| final TargetPlatform platform = Theme.of(context).platform; | ||
| final PageTransitionsTheme pageTransitionsTheme = Theme.of(context).pageTransitionsTheme; | ||
| final PageTransitionsBuilder? pageTransitionBuilder = pageTransitionsTheme.builders[platform]; | ||
| return pageTransitionBuilder is FadeForwardsPageTransitionsBuilder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the duration be a property of the page transition builders? If we add more transitions, I could see this continuing to be an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated! Thanks!
|
|
||
| static const Map<TargetPlatform, PageTransitionsBuilder> _defaultBuilders = <TargetPlatform, PageTransitionsBuilder>{ | ||
| TargetPlatform.android: ZoomPageTransitionsBuilder(), | ||
| TargetPlatform.android: FadeForwardsPageTransitionsBuilder(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we make this transition the default right away? I'm guessing this is what's breaking Google testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. The google testing failures are related to the updated behaviors like the duration change and the added ColoredBox. Maybe we can use useMaterial3 to control the default? But it also defaults to true now so using it won't fix the google testing. A migration guide and an announcement are probably also needed:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we maybe add the builder as an option in this PR but not make it the default? Then put out an announcement that we are going to transfer over to this new transition being the default, and if they want to opt out ahead of time they can set the zoom transition as their default in their theme. Then they could either, switch to using it early and migrate their tests themselves, explicitly set the zoom transition builder in their themes for all platforms needed, or let it merge later and break their tests, but they'll have warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I think this can help land the change in a soft breaking manner😄! Let me separate this PR.
chunhtai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overal LGTM,
I also vaguely remember @jonahwilliams mentioned some performance issue with old transition. will the issue still persist after the change?
| theme: ThemeData( | ||
| pageTransitionsTheme: PageTransitionsTheme( | ||
| builders: Map<TargetPlatform, PageTransitionsBuilder>.fromIterable( | ||
| TargetPlatform.values, value: (_) => const FadeForwardsPageTransitionsBuilder() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in example page_transition_theme.0.dart, there was a comment said the default is FadeForwardsPageTransitionsBuilder if not specify, is this override needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not specify, I think on iOS and macOS platforms, it will default to CupertinoPageTransitionsBuilder(), and in this example, I just wanted to show the new page transition, so I just override everything. Do you think if this is necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then I think the comment in page_transition_theme.0.dart should be updated as the default may not always be FadeForwardsPageTransitionsBuilder when unspecified.
|
|
||
| import 'package:flutter/material.dart'; | ||
|
|
||
| /// Flutter code sample for [PageTransitionsTheme]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can use some more explanation. I assume this is to show case the new material transition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, just updated! Thanks!
| expect(find.byType(FlutterLogo), findsOneWidget); | ||
| expect(find.byType(Padding), findsAtLeast(1)); | ||
| expect(find.byType(SlideTransition), findsOneWidget); | ||
| expect(find.byType(SlideTransition), findsAtLeast(1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new page transition also uses SlideTransition, so there are more than one in this example.
| final TargetPlatform platform = Theme.of(context).platform; | ||
| final PageTransitionsTheme pageTransitionsTheme = Theme.of(context).pageTransitionsTheme; | ||
| final PageTransitionsBuilder? pageTransitionBuilder = pageTransitionsTheme.builders[platform]; | ||
| return pageTransitionBuilder is FadeForwardsPageTransitionsBuilder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
| Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) { | ||
| final PageTransitionsTheme theme = Theme.of(context).pageTransitionsTheme; | ||
| final Duration duration = _getTransitionDuration(context); | ||
| controller?.duration = duration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After I thinking about it more, I think it should be done in TransitionRoute.didPush and didPop() to update the duration and reverseDuration directly right before forward() and reverse() is called.
That way you don't need this logic here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated! Thanks!
| /// helps avoid a black background between two page. | ||
| /// | ||
| /// Defaults to [ColorScheme.surface] | ||
| final Color? backgroundColor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have use case where people want to set a different color other than surface? it seems whichever color they pick will cause a color flash
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so! If the page has its own color(not ColorScheme.surface), changing the backgroundColor to the same color can avoid the color flash. I noticed this problem in page_transition_theme.0.dart, the two pages has their own Scaffold.backgroundColor, the first page has blueGrey as its background, so if we want to use the new builder and no color flash, we should also set the background color to Colors.blueGrey.
| /// that's similar to the one provided by Android O. | ||
| /// * [OpenUpwardsPageTransitionsBuilder], which defines a page transition | ||
| /// that's similar to the one provided by Andoird P. | ||
| /// * [ZoomPageTransitionsBuilder], which defines the default page transition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are going to keep the old transition, have we thought about having android version as part of theme? for example
ThemeData.androidVersion, and then based on version we build different default pagetransition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually think we should not encourage users to use the old page transitions and should deprecate those in the future, as they are already outdated:)
|
The performance problem was due to the scaling factor which is absent from this transition AFAIK. |
|
|
||
| @override | ||
| TickerFuture didPush() { | ||
| controller?.duration = transitionDuration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not in this class, I meant in TransitionRoute class directly
| TickerFuture didPush() { |
chunhtai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
MitchellGoodwin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
| await tester.tap(find.text('pop')); | ||
| await tester.pump(const Duration(milliseconds: 299)); | ||
| expect(find.text('page b'), findsOneWidget); | ||
| expect(find.byType(ColoredBox), findsNothing); // ColoredBox doesn't exist in CupertinoPageTransition. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Should this comment say FadeUpwardsPageTransition instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah thanks for catching this! Updated:)
|
Oh seems the last commit caused some test failures related to bottom sheet animation. Taking a look. |
4b041d6 to
e14ddbf
Compare
…e transition. (flutter/engine#56762) For flutter#158881 The new Android m3 page transition animates a saveLayer w/ opacity + slide in animation. See example video from linked PR: https://github.com/user-attachments/assets/1382374a-4e0c-4a0e-9d70-948ce12e6298 On each frame, we intersect the coverage rect of this saveLayer contents with the screen rect, and shrink it to a partial rectangle. But this changes each frame, which forces us to re-allocate a large texture each frame, causing performance issues. Why not ignore the cull rect entirely? We sometimes ignore the cull rect for the image filter layer for similar reasons, but from observation, the sizes of these saveLayer can be slightly larger than the screen for flutter gallery. Instead, I attempted to use the cull rect size to shrink the saveLayer by shifting the origin before intersecting. I think this should be safe to do, as I believe it could only leave the coverage as larger than it would have been and not smaller.
This PR is to add a new page transition for Material 3.
The new builder matches the latest Android page transition behavior; while the new page slides in from right to left, it fades in at the same time and the old page slides out from right to left, fading out at the same time. When both pages are fading in/out, the black background might show up, so I added a
ColoredBoxfor the slides-out page whose color defaults toColorScheme.surface. ThebackgroundColorproperty can be used to customize the default transition color.This demo shows the forward and backward behaviors.
page_transition.mov
Fixes: #142352
Pre-launch Checklist
///).