Skip to content

Commit 18c325a

Browse files
authored
Add scrim color parameter to _ZoomEnterTransitionPainter (flutter#152815)
Implements flutter#152064 There is currently no test here as I am not sure how to do it efficiently, I tried making the painter public and adding the visibleForTestinhg attribute, but then I need to add comments to everything... And even when I did that I did not know how to test the painter itself maybe via Golden tests? I have not done those in the Flutter repo yet. And if it can be done without them then that is definitely a better way. I'll wait for what the review says I should do.
1 parent 8dace15 commit 18c325a

File tree

2 files changed

+125
-5
lines changed

2 files changed

+125
-5
lines changed

packages/flutter/lib/src/material/page_transitions_theme.dart

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ class _ZoomPageTransition extends StatelessWidget {
204204
required this.secondaryAnimation,
205205
required this.allowSnapshotting,
206206
required this.allowEnterRouteSnapshotting,
207+
this.backgroundColor,
207208
this.child,
208209
});
209210

@@ -253,6 +254,11 @@ class _ZoomPageTransition extends StatelessWidget {
253254
/// routes.
254255
final bool allowSnapshotting;
255256

257+
/// The color of the scrim (background) that fades in and out during the transition.
258+
///
259+
/// If not provided, defaults to current theme's [ColorScheme.surface] color.
260+
final Color? backgroundColor;
261+
256262
/// The widget below this widget in the tree.
257263
///
258264
/// This widget will transition in and out as driven by [animation] and
@@ -270,7 +276,7 @@ class _ZoomPageTransition extends StatelessWidget {
270276

271277
@override
272278
Widget build(BuildContext context) {
273-
final Color backgroundColor = Theme.of(context).colorScheme.surface;
279+
final Color enterTransitionBackgroundColor = backgroundColor ?? Theme.of(context).colorScheme.surface;
274280
return DualTransitionBuilder(
275281
animation: animation,
276282
forwardBuilder: (
@@ -281,7 +287,7 @@ class _ZoomPageTransition extends StatelessWidget {
281287
return _ZoomEnterTransition(
282288
animation: animation,
283289
allowSnapshotting: allowSnapshotting && allowEnterRouteSnapshotting,
284-
backgroundColor: backgroundColor,
290+
backgroundColor: enterTransitionBackgroundColor,
285291
child: child,
286292
);
287293
},
@@ -308,7 +314,7 @@ class _ZoomPageTransition extends StatelessWidget {
308314
animation: animation,
309315
allowSnapshotting: allowSnapshotting && allowEnterRouteSnapshotting ,
310316
reverse: true,
311-
backgroundColor: backgroundColor,
317+
backgroundColor: enterTransitionBackgroundColor,
312318
child: child,
313319
);
314320
},
@@ -672,6 +678,7 @@ class ZoomPageTransitionsBuilder extends PageTransitionsBuilder {
672678
const ZoomPageTransitionsBuilder({
673679
this.allowSnapshotting = true,
674680
this.allowEnterRouteSnapshotting = true,
681+
this.backgroundColor,
675682
});
676683

677684
/// Whether zoom page transitions will prefer to animate a snapshot of the entering
@@ -709,6 +716,11 @@ class ZoomPageTransitionsBuilder extends PageTransitionsBuilder {
709716
/// not be snapshotted.
710717
final bool allowEnterRouteSnapshotting;
711718

719+
/// The color of the scrim (background) that fades in and out during the transition.
720+
///
721+
/// If not provided, defaults to current theme's [ColorScheme.surface] color.
722+
final Color? backgroundColor;
723+
712724
// Allows devicelab benchmarks to force disable the snapshotting. This is
713725
// intended to allow us to profile and fix the underlying performance issues
714726
// for the Impeller backend.
@@ -734,6 +746,7 @@ class ZoomPageTransitionsBuilder extends PageTransitionsBuilder {
734746
secondaryAnimation: secondaryAnimation,
735747
allowSnapshotting: allowSnapshotting && route.allowSnapshotting,
736748
allowEnterRouteSnapshotting: allowEnterRouteSnapshotting,
749+
backgroundColor: backgroundColor,
737750
child: child,
738751
);
739752
}

packages/flutter/test/material/page_transitions_theme_test.dart

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ void main() {
598598

599599
// Pump till animation is half-way through.
600600
await tester.pump();
601-
await tester.pump(const Duration(milliseconds:75));
601+
await tester.pump(const Duration(milliseconds: 75));
602602

603603
// Verify that the render box is painting the right color for scaffolded pages.
604604
final RenderBox scaffoldedRenderBox = tester.firstRenderObject<RenderBox>(find.byType(MaterialApp));
@@ -614,7 +614,7 @@ void main() {
614614

615615
// Pump till animation is half-way through.
616616
await tester.pump();
617-
await tester.pump(const Duration(milliseconds:125));
617+
await tester.pump(const Duration(milliseconds: 125));
618618

619619
// Verify that the render box is painting the right color for non-scaffolded pages.
620620
final RenderBox nonScaffoldedRenderBox = tester.firstRenderObject<RenderBox>(find.byType(MaterialApp));
@@ -626,4 +626,111 @@ void main() {
626626
// Verify that the transition successfully completed.
627627
expect(find.text('Back to home route...'), findsOneWidget);
628628
}, variant: TargetPlatformVariant.all());
629+
630+
testWidgets('ZoomPageTransitionsBuilder uses developer-provided color during transition effects if provided', (WidgetTester tester) async {
631+
// Color that is being tested for presence.
632+
const Color testSurfaceColor = Colors.red;
633+
634+
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
635+
'/': (BuildContext context) => Material(
636+
child: Scaffold(
637+
appBar: AppBar(
638+
title: const Text('Home Page'),
639+
),
640+
body: Center(
641+
child: Column(
642+
mainAxisAlignment: MainAxisAlignment.center,
643+
children: <Widget>[
644+
ElevatedButton(
645+
onPressed: () {
646+
Navigator.pushNamed(context, '/scaffolded');
647+
},
648+
child: const Text('Route with scaffold!'),
649+
),
650+
ElevatedButton(
651+
onPressed: () {
652+
Navigator.pushNamed(context, '/not-scaffolded');
653+
},
654+
child: const Text('Route with NO scaffold!'),
655+
),
656+
],
657+
),
658+
),
659+
),
660+
),
661+
'/scaffolded': (BuildContext context) => Material(
662+
child: Scaffold(
663+
appBar: AppBar(
664+
title: const Text('Scaffolded Page'),
665+
),
666+
body: Center(
667+
child: ElevatedButton(
668+
onPressed: () {
669+
Navigator.pop(context);
670+
},
671+
child: const Text('Back to home route...'),
672+
),
673+
),
674+
),
675+
),
676+
'/not-scaffolded': (BuildContext context) => Material(
677+
child: Center(
678+
child: ElevatedButton(
679+
onPressed: () {
680+
Navigator.pop(context);
681+
},
682+
child: const Text('Back to home route...'),
683+
),
684+
),
685+
),
686+
};
687+
688+
await tester.pumpWidget(
689+
MaterialApp(
690+
theme: ThemeData(
691+
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue, surface: Colors.blue),
692+
pageTransitionsTheme: PageTransitionsTheme(
693+
builders: <TargetPlatform, PageTransitionsBuilder>{
694+
// Force all platforms to use ZoomPageTransitionsBuilder to test each one.
695+
for (final TargetPlatform platform in TargetPlatform.values) platform: const ZoomPageTransitionsBuilder(backgroundColor: testSurfaceColor),
696+
},
697+
),
698+
),
699+
routes: routes,
700+
),
701+
);
702+
703+
// Go to scaffolded page.
704+
await tester.tap(find.text('Route with scaffold!'));
705+
706+
// Pump till animation is half-way through.
707+
await tester.pump();
708+
await tester.pump(const Duration(milliseconds: 75));
709+
710+
// Verify that the render box is painting the right color for scaffolded pages.
711+
final RenderBox scaffoldedRenderBox = tester.firstRenderObject<RenderBox>(find.byType(MaterialApp));
712+
// Expect the color to be at exactly 12.2% opacity at this time.
713+
expect(scaffoldedRenderBox, paints..rect(color: testSurfaceColor.withOpacity(0.122)));
714+
715+
await tester.pumpAndSettle();
716+
717+
// Go back home and then go to non-scaffolded page.
718+
await tester.tap(find.text('Back to home route...'));
719+
await tester.pumpAndSettle();
720+
await tester.tap(find.text('Route with NO scaffold!'));
721+
722+
// Pump till animation is half-way through.
723+
await tester.pump();
724+
await tester.pump(const Duration(milliseconds: 125));
725+
726+
// Verify that the render box is painting the right color for non-scaffolded pages.
727+
final RenderBox nonScaffoldedRenderBox = tester.firstRenderObject<RenderBox>(find.byType(MaterialApp));
728+
// Expect the color to be at exactly 59.6% opacity at this time.
729+
expect(nonScaffoldedRenderBox, paints..rect(color: testSurfaceColor.withOpacity(0.596)));
730+
731+
await tester.pumpAndSettle();
732+
733+
// Verify that the transition successfully completed.
734+
expect(find.text('Back to home route...'), findsOneWidget);
735+
}, variant: TargetPlatformVariant.all());
629736
}

0 commit comments

Comments
 (0)