Unverified Commit 4f8a9914 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Dynamic view sizing (#138648)

Towards https://github.com/flutter/flutter/issues/134501.

This change is based on https://github.com/flutter/engine/pull/48090. It changes the `RenderView` to be dynamically sized based on its content if the `FlutterView` it is configured with allows it (i.e. the `FlutterView` has loose `FlutterView.physicalConstraints`). For that, it uses those `physicalConstraints` as input to the layout algorithm by passing them on to its child (after translating them to logical constraints via the device pixel ratio). The resulting `Size` that the `RenderView` would like to be is then communicated back to the engine by passing it to the `FlutterView.render` call.

Tests will fail until https://github.com/flutter/engine/pull/48090 has rolled into the framework.
parent b4178125
......@@ -350,7 +350,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
final FlutterView view = renderView.flutterView;
final double devicePixelRatio = view.devicePixelRatio;
return ViewConfiguration(
size: view.physicalSize / devicePixelRatio,
constraints: view.physicalConstraints / devicePixelRatio,
devicePixelRatio: devicePixelRatio,
);
}
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
import 'dart:math' as math;
import 'dart:ui' as ui show lerpDouble;
import 'dart:ui' as ui show ViewConstraints, lerpDouble;
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
......@@ -153,6 +153,13 @@ class BoxConstraints extends Constraints {
minHeight = height ?? double.infinity,
maxHeight = height ?? double.infinity;
/// Creates box constraints that match the given view constraints.
BoxConstraints.fromViewConstraints(ui.ViewConstraints constraints)
: minWidth = constraints.minWidth,
maxWidth = constraints.maxWidth,
minHeight = constraints.minHeight,
maxHeight = constraints.maxHeight;
/// The minimum width that satisfies the constraints.
final double minWidth;
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'dart:ui' as ui show FlutterView, Scene, SceneBuilder, SemanticsUpdate;
import 'dart:ui' as ui show FlutterView, Scene, SceneBuilder, SemanticsUpdate, ViewConstraints;
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
......@@ -19,14 +19,15 @@ import 'object.dart';
class ViewConfiguration {
/// Creates a view configuration.
///
/// By default, the view has zero [size] and a [devicePixelRatio] of 1.0.
/// By default, the view has [ViewConstraints] with all dimensions set to zero
/// (i.e. the view is forced to [Size.zero]) and a [devicePixelRatio] of 1.0.
const ViewConfiguration({
this.size = Size.zero,
this.constraints = const ui.ViewConstraints(maxWidth: 0.0, maxHeight: 0.0),
this.devicePixelRatio = 1.0,
});
/// The size of the output surface.
final Size size;
/// The constraints of the output surface in logical pixel.
final ui.ViewConstraints constraints;
/// The pixel density of the output surface.
final double devicePixelRatio;
......@@ -40,21 +41,34 @@ class ViewConfiguration {
return Matrix4.diagonal3Values(devicePixelRatio, devicePixelRatio, 1.0);
}
/// Transforms the provided [Size] in logical pixels to physical pixels.
///
/// The [FlutterView.render] method accepts only sizes in physical pixels,
/// but the framework operates in logical pixels. This method is used to
/// transform the logical size calculated for a [RenderView] back to a
/// physical size suitable to be passed to [FlutterView.render].
///
/// By default, this method just multiplies the provided [Size] with the
/// [devicePixelRatio].
Size toPhysicalSize(Size logicalSize) {
return logicalSize * devicePixelRatio;
}
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) {
return false;
}
return other is ViewConfiguration
&& other.size == size
&& other.constraints == constraints
&& other.devicePixelRatio == devicePixelRatio;
}
@override
int get hashCode => Object.hash(size, devicePixelRatio);
int get hashCode => Object.hash(constraints, devicePixelRatio);
@override
String toString() => '$size at ${debugFormatDouble(devicePixelRatio)}x';
String toString() => '$constraints at ${debugFormatDouble(devicePixelRatio)}x';
}
/// The root of the render tree.
......@@ -76,8 +90,10 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
RenderBox? child,
ViewConfiguration? configuration,
required ui.FlutterView view,
}) : _configuration = configuration,
_view = view {
}) : _view = view {
if (configuration != null) {
this.configuration = configuration;
}
this.child = child;
}
......@@ -105,6 +121,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
}
final ViewConfiguration? oldConfiguration = _configuration;
_configuration = value;
_constraints = BoxConstraints.fromViewConstraints(configuration.constraints);
if (_rootTransform == null) {
// [prepareInitialFrame] has not been called yet, nothing to do for now.
return;
......@@ -119,6 +136,15 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
/// Whether a [configuration] has been set.
bool get hasConfiguration => _configuration != null;
@override
BoxConstraints get constraints {
if (_constraints == null) {
throw StateError('Constraints are not available because RenderView has not been given a configuration yet.');
}
return _constraints!;
}
BoxConstraints? _constraints;
/// The [FlutterView] into which this [RenderView] will render.
ui.FlutterView get flutterView => _view;
final ui.FlutterView _view;
......@@ -188,12 +214,13 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
@override
void performLayout() {
assert(_rootTransform != null);
_size = configuration.size;
assert(_size.isFinite);
final bool sizedByChild = !constraints.isTight;
if (child != null) {
child!.layout(BoxConstraints.tight(_size));
child!.layout(constraints, parentUsesSize: sizedByChild);
}
_size = sizedByChild && child != null ? child!.size : constraints.smallest;
assert(size.isFinite);
assert(constraints.isSatisfiedBy(size));
}
/// Determines the set of render objects located at the given position.
......@@ -253,7 +280,8 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
if (automaticSystemUiAdjustment) {
_updateSystemChrome();
}
_view.render(scene);
assert(configuration.constraints.isSatisfiedBy(size));
_view.render(scene, size: configuration.toPhysicalSize(size));
scene.dispose();
assert(() {
if (debugRepaintRainbowEnabled || debugRepaintTextRainbowEnabled) {
......
......@@ -259,7 +259,8 @@ void main() {
r' debug mode enabled - [a-zA-Z]+\n'
r' view size: Size\(2400\.0, 1800\.0\) \(in physical pixels\)\n'
r' device pixel ratio: 3\.0 \(physical pixels per logical pixel\)\n'
r' configuration: Size\(800\.0, 600\.0\) at 3\.0x \(in logical pixels\)\n'
r' configuration: ViewConstraints\(w=800\.0, h=600\.0\) at 3\.0x \(in\n'
r' logical pixels\)\n'
r'$',
),
});
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -167,4 +169,17 @@ void main() {
expect(copy.minHeight, 11.0);
expect(copy.maxHeight, 18.0);
});
test('BoxConstraints.fromViewConstraints', () {
final BoxConstraints unconstrained = BoxConstraints.fromViewConstraints(
const ViewConstraints(),
);
expect(unconstrained, const BoxConstraints());
final BoxConstraints constraints = BoxConstraints.fromViewConstraints(
const ViewConstraints(minWidth: 1, maxWidth: 2, minHeight: 3, maxHeight: 4),
);
expect(constraints, const BoxConstraints(minWidth: 1, maxWidth: 2, minHeight: 3, maxHeight: 4));
});
}
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' show ViewConstraints;
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -32,8 +34,8 @@ class TestLayout {
void main() {
TestRenderingFlutterBinding.ensureInitialized();
const ViewConfiguration testConfiguration = ViewConfiguration(
size: Size(800.0, 600.0),
final ViewConfiguration testConfiguration = ViewConfiguration(
constraints: ViewConstraints.tight(const Size(800.0, 600.0)),
);
test('onscreen layout does not affect offscreen', () {
......
......@@ -18,7 +18,7 @@ void main() {
binding.addRenderView(view);
expect(binding.renderViews, contains(view));
expect(view.configuration.devicePixelRatio, flutterView.devicePixelRatio);
expect(view.configuration.size, flutterView.physicalSize / flutterView.devicePixelRatio);
expect(view.configuration.constraints, ViewConstraints.tight(flutterView.physicalSize) / flutterView.devicePixelRatio);
binding.removeRenderView(view);
expect(binding.renderViews, isEmpty);
......@@ -51,13 +51,17 @@ void main() {
final RenderView view = RenderView(view: flutterView);
binding.addRenderView(view);
expect(view.configuration.devicePixelRatio, 2.5);
expect(view.configuration.size, const Size(160.0, 240.0));
expect(view.configuration.constraints.isTight, isTrue);
expect(view.configuration.constraints.minWidth, 160.0);
expect(view.configuration.constraints.minHeight, 240.0);
flutterView.devicePixelRatio = 3.0;
flutterView.physicalSize = const Size(300, 300);
binding.handleMetricsChanged();
expect(view.configuration.devicePixelRatio, 3.0);
expect(view.configuration.size, const Size(100.0, 100.0));
expect(view.configuration.constraints.isTight, isTrue);
expect(view.configuration.constraints.minWidth, 100.0);
expect(view.configuration.constraints.minHeight, 100.0);
binding.removeRenderView(view);
});
......@@ -183,6 +187,8 @@ class FakeFlutterView extends Fake implements FlutterView {
@override
Size physicalSize;
@override
ViewConstraints get physicalConstraints => ViewConstraints.tight(physicalSize);
@override
ViewPadding padding;
List<Scene> renderedScenes = <Scene>[];
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' show ViewConstraints;
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -16,14 +18,14 @@ void main() {
Size size = const Size(20, 20),
double devicePixelRatio = 2.0,
}) {
return ViewConfiguration(size: size, devicePixelRatio: devicePixelRatio);
return ViewConfiguration(constraints: ViewConstraints.tight(size), devicePixelRatio: devicePixelRatio);
}
group('RenderView', () {
test('accounts for device pixel ratio in paintBounds', () {
layout(RenderAspectRatio(aspectRatio: 1.0));
pumpFrame();
final Size logicalSize = TestRenderingFlutterBinding.instance.renderView.configuration.size;
final Size logicalSize = TestRenderingFlutterBinding.instance.renderView.size;
final double devicePixelRatio = TestRenderingFlutterBinding.instance.renderView.configuration.devicePixelRatio;
final Size physicalSize = logicalSize * devicePixelRatio;
expect(TestRenderingFlutterBinding.instance.renderView.paintBounds, Offset.zero & physicalSize);
......@@ -126,11 +128,38 @@ void main() {
final RenderView view = RenderView(
view: RendererBinding.instance.platformDispatcher.views.single,
);
view.configuration = const ViewConfiguration(size: Size(100, 200), devicePixelRatio: 3.0);
view.configuration = const ViewConfiguration(size: Size(200, 300), devicePixelRatio: 2.0);
view.configuration = ViewConfiguration(constraints: ViewConstraints.tight(const Size(100, 200)), devicePixelRatio: 3.0);
view.configuration = ViewConfiguration(constraints: ViewConstraints.tight(const Size(200, 300)), devicePixelRatio: 2.0);
PipelineOwner().rootNode = view;
view.prepareInitialFrame();
});
test('Constraints are derived from configuration', () {
const ViewConfiguration config = ViewConfiguration(
constraints: ViewConstraints(minWidth: 1, maxWidth: 2, minHeight: 3, maxHeight: 4),
devicePixelRatio: 3.0,
);
const BoxConstraints constraints = BoxConstraints(minWidth: 1, maxWidth: 2, minHeight: 3, maxHeight: 4);
// Configuration set via setter.
final RenderView view = RenderView(
view: RendererBinding.instance.platformDispatcher.views.single,
);
expect(() => view.constraints, throwsA(isA<StateError>().having(
(StateError e) => e.message,
'message',
contains('RenderView has not been given a configuration yet'),
)));
view.configuration = config;
expect(view.constraints, constraints);
// Configuration set in constructor.
final RenderView view2 = RenderView(
view: RendererBinding.instance.platformDispatcher.views.single,
configuration: config,
);
expect(view2.constraints, constraints);
});
}
const Color orange = Color(0xFFFF9000);
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' show FlutterView;
import 'dart:ui' show FlutterView, ViewConstraints;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
......@@ -36,7 +36,7 @@ class ScheduledFrameTrackingBindings extends AutomatedTestWidgetsFlutterBinding
class OffscreenRenderView extends RenderView {
OffscreenRenderView({required super.view}) : super(
configuration: const ViewConfiguration(size: _kTestViewSize),
configuration: ViewConfiguration(constraints: ViewConstraints.tight(_kTestViewSize)),
);
@override
......
......@@ -218,7 +218,8 @@ void main() {
' │ debug mode enabled - ${Platform.operatingSystem}\n'
' │ view size: Size(2400.0, 1800.0) (in physical pixels)\n'
' │ device pixel ratio: 3.0 (physical pixels per logical pixel)\n'
' │ configuration: Size(800.0, 600.0) at 3.0x (in logical pixels)\n'
' │ configuration: ViewConstraints(w=800.0, h=600.0) at 3.0x (in\n'
' │ logical pixels)\n'
' │\n'
' └─child: RenderRepaintBoundary#00000\n'
' │ needs compositing\n'
......@@ -392,7 +393,8 @@ void main() {
' │ debug mode enabled - ${Platform.operatingSystem}\n'
' │ view size: Size(2400.0, 1800.0) (in physical pixels)\n'
' │ device pixel ratio: 3.0 (physical pixels per logical pixel)\n'
' │ configuration: Size(800.0, 600.0) at 3.0x (in logical pixels)\n'
' │ configuration: ViewConstraints(w=800.0, h=600.0) at 3.0x (in\n'
' │ logical pixels)\n'
' │\n'
' └─child: RenderRepaintBoundary#00000\n'
' │ needs compositing\n'
......
......@@ -450,6 +450,68 @@ void main() {
});
expect(children, isNot(contains(rawViewOwner)));
});
testWidgetsWithLeakTracking('RenderView does not use size of child if constraints are tight', (WidgetTester tester) async {
const Size physicalSize = Size(300, 600);
final Size logicalSize = physicalSize / tester.view.devicePixelRatio;
tester.view.physicalConstraints = ViewConstraints.tight(physicalSize);
await tester.pumpWidget(const Placeholder());
final RenderView renderView = tester.renderObject<RenderView>(find.byType(View));
expect(renderView.constraints, BoxConstraints.tight(logicalSize));
expect(renderView.size, logicalSize);
final RenderBox child = renderView.child!;
expect(child.constraints, BoxConstraints.tight(logicalSize));
expect(child.debugCanParentUseSize, isFalse);
expect(child.size, logicalSize);
});
testWidgetsWithLeakTracking('RenderView sizes itself to child if constraints allow it (unconstrained)', (WidgetTester tester) async {
const Size size = Size(300, 600);
tester.view.physicalConstraints = const ViewConstraints(); // unconstrained
await tester.pumpWidget(SizedBox.fromSize(size: size));
final RenderView renderView = tester.renderObject<RenderView>(find.byType(View));
expect(renderView.constraints, const BoxConstraints());
expect(renderView.size, size);
final RenderBox child = renderView.child!;
expect(child.constraints, const BoxConstraints());
expect(child.debugCanParentUseSize, isTrue);
expect(child.size, size);
});
testWidgetsWithLeakTracking('RenderView sizes itself to child if constraints allow it (constrained)', (WidgetTester tester) async {
const Size size = Size(30, 60);
const ViewConstraints viewConstraints = ViewConstraints(maxWidth: 333, maxHeight: 666);
final BoxConstraints boxConstraints = BoxConstraints.fromViewConstraints(viewConstraints / tester.view.devicePixelRatio);
tester.view.physicalConstraints = viewConstraints;
await tester.pumpWidget(SizedBox.fromSize(size: size));
final RenderView renderView = tester.renderObject<RenderView>(find.byType(View));
expect(renderView.constraints, boxConstraints);
expect(renderView.size, size);
final RenderBox child = renderView.child!;
expect(child.constraints, boxConstraints);
expect(child.debugCanParentUseSize, isTrue);
expect(child.size, size);
});
testWidgetsWithLeakTracking('RenderView respects constraints when child wants to be bigger than allowed', (WidgetTester tester) async {
const Size size = Size(3000, 6000);
const ViewConstraints viewConstraints = ViewConstraints(maxWidth: 300, maxHeight: 600);
tester.view.physicalConstraints = viewConstraints;
await tester.pumpWidget(SizedBox.fromSize(size: size));
final RenderView renderView = tester.renderObject<RenderView>(find.byType(View));
expect(renderView.size, const Size(100, 200)); // viewConstraints.biggest / devicePixelRatio
final RenderBox child = renderView.child!;
expect(child.debugCanParentUseSize, isTrue);
expect(child.size, const Size(100, 200));
});
}
Future<void> pumpWidgetWithoutViewWrapper({required WidgetTester tester, required Widget widget}) {
......
......@@ -4696,7 +4696,14 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(renderObject!['description'], contains('RenderView'));
expect(result['parentRenderElement'], isNull);
expect(result['constraints'], isNull);
final Map<String, Object?>? constraints = result['constraints'] as Map<String, Object?>?;
expect(constraints, isNotNull);
expect(constraints!['type'], equals('BoxConstraints'));
expect(constraints['minWidth'], equals('800.0'));
expect(constraints['minHeight'], equals('600.0'));
expect(constraints['maxWidth'], equals('800.0'));
expect(constraints['maxHeight'], equals('600.0'));
expect(result['isBox'], isNull);
final Map<String, Object?>? size = result['size'] as Map<String, Object?>?;
......
......@@ -560,7 +560,7 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
final FlutterView view = renderView.flutterView;
if (_surfaceSize != null && view == platformDispatcher.implicitView) {
return ViewConfiguration(
size: _surfaceSize!,
constraints: ui.ViewConstraints.tight(_surfaceSize!),
devicePixelRatio: view.devicePixelRatio,
);
}
......@@ -1831,7 +1831,7 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
final Map<int, _LiveTestPointerRecord>? pointerIdToRecord = _renderViewToPointerIdToPointerRecord[renderView];
if (pointerIdToRecord != null && pointerIdToRecord.isNotEmpty) {
final double radius = renderView.configuration.size.shortestSide * 0.05;
final double radius = renderView.size.shortestSide * 0.05;
final Path path = Path()
..addOval(Rect.fromCircle(center: Offset.zero, radius: radius))
..moveTo(0.0, -radius * 2.0)
......@@ -2115,9 +2115,10 @@ class TestViewConfiguration extends ViewConfiguration {
/// Creates a [TestViewConfiguration] with the given size and view.
///
/// The [size] defaults to 800x600.
TestViewConfiguration.fromView({required ui.FlutterView view, super.size = _kDefaultTestViewportSize})
TestViewConfiguration.fromView({required ui.FlutterView view, Size size = _kDefaultTestViewportSize})
: _paintMatrix = _getMatrix(size, view.devicePixelRatio, view),
super(devicePixelRatio: view.devicePixelRatio);
_physicalSize = view.physicalSize,
super(devicePixelRatio: view.devicePixelRatio, constraints: ui.ViewConstraints.tight(size));
static Matrix4 _getMatrix(Size size, double devicePixelRatio, ui.FlutterView window) {
final double inverseRatio = devicePixelRatio / window.devicePixelRatio;
......@@ -2148,6 +2149,11 @@ class TestViewConfiguration extends ViewConfiguration {
@override
Matrix4 toMatrix() => _paintMatrix.clone();
final Size _physicalSize;
@override
Size toPhysicalSize(Size logicalSize) => _physicalSize;
@override
String toString() => 'TestViewConfiguration';
}
......
......@@ -751,6 +751,9 @@ class TestFlutterView implements FlutterView {
/// can only be set in a test environment to emulate different view
/// configurations. A standard [FlutterView] is not mutable from the framework.
///
/// Setting this value also sets [physicalConstraints] to tight constraints
/// based on the given size.
///
/// See also:
///
/// * [FlutterView.physicalSize] for the standard implementation
......@@ -761,12 +764,39 @@ class TestFlutterView implements FlutterView {
Size? _physicalSize;
set physicalSize(Size value) {
_physicalSize = value;
platformDispatcher.onMetricsChanged?.call();
// For backwards compatibility the constraints are set based on the provided size.
physicalConstraints = ViewConstraints.tight(value);
}
/// Resets [physicalSize] to the default value for this view.
/// Resets [physicalSize] (and implicitly also the [physicalConstraints]) to
/// the default value for this view.
void resetPhysicalSize() {
_physicalSize = null;
resetPhysicalConstraints();
}
/// The physical constraints to use for this test.
///
/// Defaults to the value provided by [FlutterView.physicalConstraints]. This
/// can only be set in a test environment to emulate different view
/// configurations. A standard [FlutterView] is not mutable from the framework.
///
/// See also:
///
/// * [FlutterView.physicalConstraints] for the standard implementation
/// * [physicalConstraints] to reset this value specifically
/// * [reset] to reset all test values for this view
@override
ViewConstraints get physicalConstraints => _physicalConstraints ?? _view.physicalConstraints;
ViewConstraints? _physicalConstraints;
set physicalConstraints(ViewConstraints value) {
_physicalConstraints = value;
platformDispatcher.onMetricsChanged?.call();
}
/// Resets [physicalConstraints] to the default value for this view.
void resetPhysicalConstraints() {
_physicalConstraints = null;
platformDispatcher.onMetricsChanged?.call();
}
......@@ -875,8 +905,7 @@ class TestFlutterView implements FlutterView {
@override
void render(Scene scene, {Size? size}) {
// TODO(goderbauer): Wire through size after https://github.com/flutter/engine/pull/48090 rolled in.
_view.render(scene);
_view.render(scene, size: size);
}
@override
......@@ -901,6 +930,7 @@ class TestFlutterView implements FlutterView {
resetDisplayFeatures();
resetPadding();
resetPhysicalSize();
// resetPhysicalConstraints is implicitly called by resetPhysicalSize.
resetSystemGestureInsets();
resetViewInsets();
resetViewPadding();
......@@ -1637,8 +1667,7 @@ class TestWindow implements SingletonFlutterWindow {
)
@override
void render(Scene scene, {Size? size}) {
// TODO(goderbauer): Wire through size after https://github.com/flutter/engine/pull/48090 rolled in.
_view.render(scene);
_view.render(scene, size: size);
}
@Deprecated(
......
......@@ -124,6 +124,19 @@ void main() {
);
});
testWidgets('faking physicalSize fakes physicalConstraints', (WidgetTester tester) async {
const Size fakeSize = Size(50, 50);
verifyPropertyFaked<ViewConstraints>(
tester: tester,
realValue: trueImplicitView().physicalConstraints,
fakeValue: ViewConstraints.tight(fakeSize),
propertyRetriever: () => boundImplicitView().physicalConstraints,
propertyFaker: (_, __) {
tester.view.physicalSize = fakeSize;
},
);
});
testWidgets('can reset physicalSize', (WidgetTester tester) async {
verifyPropertyReset<Size>(
tester: tester,
......@@ -138,6 +151,47 @@ void main() {
);
});
testWidgets('resetting physicalSize resets physicalConstraints', (WidgetTester tester) async {
const Size fakeSize = Size(50, 50);
verifyPropertyReset<ViewConstraints>(
tester: tester,
fakeValue: ViewConstraints.tight(fakeSize),
propertyRetriever: () => boundImplicitView().physicalConstraints,
propertyResetter: () {
tester.view.resetPhysicalSize();
},
propertyFaker: (_) {
tester.view.physicalSize = fakeSize;
},
);
});
testWidgets('can fake physicalConstraints', (WidgetTester tester) async {
verifyPropertyFaked<ViewConstraints>(
tester: tester,
realValue: trueImplicitView().physicalConstraints,
fakeValue: const ViewConstraints(minWidth: 1, maxWidth: 2, minHeight: 3, maxHeight: 4),
propertyRetriever: () => boundImplicitView().physicalConstraints,
propertyFaker: (_, ViewConstraints fakeValue) {
tester.view.physicalConstraints = fakeValue;
},
);
});
testWidgets('can reset physicalConstraints', (WidgetTester tester) async {
verifyPropertyReset<ViewConstraints>(
tester: tester,
fakeValue: const ViewConstraints(minWidth: 1, maxWidth: 2, minHeight: 3, maxHeight: 4),
propertyRetriever: () => boundImplicitView().physicalConstraints,
propertyResetter: () {
tester.view.resetPhysicalConstraints();
},
propertyFaker: (ViewConstraints fakeValue) {
tester.view.physicalConstraints = fakeValue;
},
);
});
testWidgets('can fake systemGestureInsets', (WidgetTester tester) async {
verifyPropertyFaked<ViewPadding>(
tester: tester,
......
......@@ -83,7 +83,7 @@ No widgets found at Offset(1.0, 1.0).
),
);
final Size originalSize = tester.binding.createViewConfigurationFor(tester.binding.renderView).size; // ignore: deprecated_member_use
final Size originalSize = tester.binding.renderView.size; // ignore: deprecated_member_use
await tester.binding.setSurfaceSize(const Size(2000, 1800));
try {
await tester.pump();
......
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