Unverified Commit a7fe5365 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[framework] re-rasterize when window size or insets changes (#113647)

parent 15a4b009
...@@ -291,6 +291,7 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr ...@@ -291,6 +291,7 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
bool get useSnapshot => !kIsWeb && widget.allowSnapshotting; bool get useSnapshot => !kIsWeb && widget.allowSnapshotting;
late _ZoomEnterTransitionPainter delegate; late _ZoomEnterTransitionPainter delegate;
MediaQueryData? mediaQueryData;
static final Animatable<double> _fadeInTransition = Tween<double>( static final Animatable<double> _fadeInTransition = Tween<double>(
begin: 0.0, begin: 0.0,
...@@ -355,6 +356,18 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr ...@@ -355,6 +356,18 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
super.didUpdateWidget(oldWidget); 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 @override
void dispose() { void dispose() {
widget.animation.removeListener(onAnimationValueChange); widget.animation.removeListener(onAnimationValueChange);
...@@ -394,6 +407,7 @@ class _ZoomExitTransition extends StatefulWidget { ...@@ -394,6 +407,7 @@ class _ZoomExitTransition extends StatefulWidget {
class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTransitionBase { class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTransitionBase {
late _ZoomExitTransitionPainter delegate; late _ZoomExitTransitionPainter delegate;
MediaQueryData? mediaQueryData;
// See SnapshotWidget doc comment, this is disabled on web because the HTML backend doesn't // 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 // support this functionality and the canvaskit backend uses a single thread for UI and raster
...@@ -458,6 +472,18 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTran ...@@ -458,6 +472,18 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTran
super.didUpdateWidget(oldWidget); 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 @override
void dispose() { void dispose() {
widget.animation.removeListener(onAnimationValueChange); widget.animation.removeListener(onAnimationValueChange);
...@@ -804,6 +830,13 @@ mixin _ZoomTransitionBase { ...@@ -804,6 +830,13 @@ mixin _ZoomTransitionBase {
break; 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 { class _ZoomEnterTransitionPainter extends SnapshotPainter {
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
@Tags(<String>['reduced-test-set'])
import 'package:flutter/cupertino.dart' show CupertinoPageRoute; import 'package:flutter/cupertino.dart' show CupertinoPageRoute;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -234,6 +236,47 @@ void main() { ...@@ -234,6 +236,47 @@ void main() {
expect(find.text('Page 2'), findsNothing); expect(find.text('Page 2'), findsNothing);
}, variant: TargetPlatformVariant.only(TargetPlatform.android)); }, 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 { testWidgets('test fullscreen dialog transition', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
......
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