Skip to content

Commit 84fc52e

Browse files
authored
InteractiveViewer with a changing screen size (flutter#60532)
1 parent 14a4ed5 commit 84fc52e

File tree

2 files changed

+57
-15
lines changed

2 files changed

+57
-15
lines changed

packages/flutter/lib/src/widgets/interactive_viewer.dart

+7-15
Original file line numberDiff line numberDiff line change
@@ -494,11 +494,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
494494

495495
// The _boundaryRect is calculated by adding the boundaryMargin to the size of
496496
// the child.
497-
Rect _boundaryRectCached;
498497
Rect get _boundaryRect {
499-
if (_boundaryRectCached != null) {
500-
return _boundaryRectCached;
501-
}
502498
assert(_childKey.currentContext != null);
503499
assert(!widget.boundaryMargin.left.isNaN);
504500
assert(!widget.boundaryMargin.right.isNaN);
@@ -507,15 +503,15 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
507503

508504
final RenderBox childRenderBox = _childKey.currentContext.findRenderObject() as RenderBox;
509505
final Size childSize = childRenderBox.size;
510-
_boundaryRectCached = widget.boundaryMargin.inflateRect(Offset.zero & childSize);
506+
final Rect boundaryRect = widget.boundaryMargin.inflateRect(Offset.zero & childSize);
511507
// Boundaries that are partially infinite are not allowed because Matrix4's
512508
// rotation and translation methods don't handle infinites well.
513-
assert(_boundaryRectCached.isFinite ||
514-
(_boundaryRectCached.left.isInfinite
515-
&& _boundaryRectCached.top.isInfinite
516-
&& _boundaryRectCached.right.isInfinite
517-
&& _boundaryRectCached.bottom.isInfinite), 'boundaryRect must either be infinite in all directions or finite in all directions.');
518-
return _boundaryRectCached;
509+
assert(boundaryRect.isFinite ||
510+
(boundaryRect.left.isInfinite
511+
&& boundaryRect.top.isInfinite
512+
&& boundaryRect.right.isInfinite
513+
&& boundaryRect.bottom.isInfinite), 'boundaryRect must either be infinite in all directions or finite in all directions.');
514+
return boundaryRect;
519515
}
520516

521517
// The Rect representing the child's parent.
@@ -917,10 +913,6 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
917913
@override
918914
void didUpdateWidget(InteractiveViewer oldWidget) {
919915
super.didUpdateWidget(oldWidget);
920-
if (widget.child != oldWidget.child || widget.boundaryMargin != oldWidget.boundaryMargin) {
921-
_boundaryRectCached = null;
922-
}
923-
924916
// Handle all cases of needing to dispose and initialize
925917
// transformationControllers.
926918
if (oldWidget.transformationController == null) {

packages/flutter/test/widgets/interactive_viewer_test.dart

+50
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,56 @@ void main() {
450450

451451
expect(transformationController.value.getMaxScaleOnAxis(), equals(1.0));
452452
});
453+
454+
testWidgets('viewport changes size', (WidgetTester tester) async {
455+
final TransformationController transformationController = TransformationController();
456+
await tester.pumpWidget(
457+
MaterialApp(
458+
home: Scaffold(
459+
body: Center(
460+
child: InteractiveViewer(
461+
transformationController: transformationController,
462+
child: Container(),
463+
),
464+
),
465+
),
466+
),
467+
);
468+
469+
expect(transformationController.value, equals(Matrix4.identity()));
470+
471+
// Attempting to drag to pan doesn't work because the child fits inside
472+
// the viewport and has a tight boundary.
473+
final Offset childOffset = tester.getTopLeft(find.byType(Container));
474+
final Offset childInterior = Offset(
475+
childOffset.dx + 20.0,
476+
childOffset.dy + 20.0,
477+
);
478+
TestGesture gesture = await tester.startGesture(childInterior);
479+
addTearDown(gesture.removePointer);
480+
await tester.pump();
481+
await gesture.moveTo(childOffset);
482+
await tester.pump();
483+
await gesture.up();
484+
await tester.pumpAndSettle();
485+
expect(transformationController.value, equals(Matrix4.identity()));
486+
487+
// Shrink the size of the screen.
488+
tester.binding.window.physicalSizeTestValue = const Size(100.0, 100.0);
489+
addTearDown(tester.binding.window.clearPhysicalSizeTestValue);
490+
await tester.pump();
491+
492+
// Attempting to drag to pan still doesn't work, because the image has
493+
// resized itself to fit the new screen size, and InteractiveViewer has
494+
// updated its measurements to take that into consideration.
495+
gesture = await tester.startGesture(childInterior);
496+
await tester.pump();
497+
await gesture.moveTo(childOffset);
498+
await tester.pump();
499+
await gesture.up();
500+
await tester.pumpAndSettle();
501+
expect(transformationController.value, equals(Matrix4.identity()));
502+
});
453503
});
454504

455505
group('getNearestPointOnLine', () {

0 commit comments

Comments
 (0)