Skip to content

Commit

Permalink
[framework] re-rasterize when window size or insets changes (flutter#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jonahwilliams committed Oct 24, 2022
1 parent 15a4b00 commit a7fe536
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
33 changes: 33 additions & 0 deletions packages/flutter/lib/src/material/page_transitions_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
bool get useSnapshot => !kIsWeb && widget.allowSnapshotting;

late _ZoomEnterTransitionPainter delegate;
MediaQueryData? mediaQueryData;

static final Animatable<double> _fadeInTransition = Tween<double>(
begin: 0.0,
Expand Down Expand Up @@ -355,6 +356,18 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
super.didUpdateWidget(oldWidget);
}

@override
void didChangeDependencies() {
// If the screen size changes during the transition, perhaps due to
// a keyboard dismissal, then ensure that contents are re-rasterized once.
final MediaQueryData? data = MediaQuery.maybeOf(context);
if (mediaQueryDataChanged(mediaQueryData, data)) {
controller.clear();
}
mediaQueryData = data;
super.didChangeDependencies();
}

@override
void dispose() {
widget.animation.removeListener(onAnimationValueChange);
Expand Down Expand Up @@ -394,6 +407,7 @@ class _ZoomExitTransition extends StatefulWidget {

class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTransitionBase {
late _ZoomExitTransitionPainter delegate;
MediaQueryData? mediaQueryData;

// See SnapshotWidget doc comment, this is disabled on web because the HTML backend doesn't
// support this functionality and the canvaskit backend uses a single thread for UI and raster
Expand Down Expand Up @@ -458,6 +472,18 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTran
super.didUpdateWidget(oldWidget);
}

@override
void didChangeDependencies() {
// If the screen size changes during the transition, perhaps due to
// a keyboard dismissal, then ensure that contents are re-rasterized once.
final MediaQueryData? data = MediaQuery.maybeOf(context);
if (mediaQueryDataChanged(mediaQueryData, data)) {
controller.clear();
}
mediaQueryData = data;
super.didChangeDependencies();
}

@override
void dispose() {
widget.animation.removeListener(onAnimationValueChange);
Expand Down Expand Up @@ -804,6 +830,13 @@ mixin _ZoomTransitionBase {
break;
}
}

// Whether any of the properties that would impact the page transition
// changed.
bool mediaQueryDataChanged(MediaQueryData? oldData, MediaQueryData? newData) {
return oldData?.size != newData?.size ||
oldData?.viewInsets != newData?.viewInsets;
}
}

class _ZoomEnterTransitionPainter extends SnapshotPainter {
Expand Down
43 changes: 43 additions & 0 deletions packages/flutter/test/material/page_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@Tags(<String>['reduced-test-set'])
import 'package:flutter/cupertino.dart' show CupertinoPageRoute;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
Expand Down Expand Up @@ -234,6 +236,47 @@ void main() {
expect(find.text('Page 2'), findsNothing);
}, variant: TargetPlatformVariant.only(TargetPlatform.android));

testWidgets('test page transition (_ZoomPageTransition) with rasterization re-rasterizes when window size changes', (WidgetTester tester) async {
// Shrink the window size.
late Size oldSize;
try {
oldSize = tester.binding.window.physicalSize;
tester.binding.window.physicalSizeTestValue = const Size(1000, 1000);

final Key key = GlobalKey();
await tester.pumpWidget(
RepaintBoundary(
key: key,
child: MaterialApp(
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute<void>(
builder: (BuildContext context) {
return const Material(child: SizedBox.shrink());
},
);
},
),
),
);

tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');
await tester.pump();
await tester.pump(const Duration(milliseconds: 50));

await expectLater(find.byKey(key), matchesGoldenFile('zoom_page_transition.small.png'));

// Increase the window size.
tester.binding.window.physicalSizeTestValue = const Size(1000, 2000);

await tester.pump();
await tester.pump(const Duration(milliseconds: 50));

await expectLater(find.byKey(key), matchesGoldenFile('zoom_page_transition.big.png'));
} finally {
tester.binding.window.physicalSizeTestValue = oldSize;
}
}, variant: TargetPlatformVariant.only(TargetPlatform.android), skip: kIsWeb); // [intended] rasterization is not used on the web.

testWidgets('test fullscreen dialog transition', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
Expand Down

0 comments on commit a7fe536

Please sign in to comment.