Implement dryLayout for RenderAnimatedSize (#71097)
This commit is contained in:
parent
13ce828e32
commit
b18f1b81fe
@ -223,6 +223,38 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
||||
_hasVisualOverflow = true;
|
||||
}
|
||||
|
||||
@override
|
||||
Size computeDryLayout(BoxConstraints constraints) {
|
||||
if (child == null || constraints.isTight) {
|
||||
return constraints.smallest;
|
||||
}
|
||||
|
||||
// This simplified version of performLayout only calculates the current
|
||||
// size without modifying global state. See performLayout for comments
|
||||
// explaining the rational behind the implementation.
|
||||
final Size childSize = child!.getDryLayout(constraints);
|
||||
assert(_state != null);
|
||||
switch (_state) {
|
||||
case RenderAnimatedSizeState.start:
|
||||
return constraints.constrain(childSize);
|
||||
case RenderAnimatedSizeState.stable:
|
||||
if (_sizeTween.end != childSize) {
|
||||
return constraints.constrain(size);
|
||||
} else if (_controller.value == _controller.upperBound) {
|
||||
return constraints.constrain(childSize);
|
||||
}
|
||||
break;
|
||||
case RenderAnimatedSizeState.unstable:
|
||||
case RenderAnimatedSizeState.changed:
|
||||
if (_sizeTween.end != childSize) {
|
||||
return constraints.constrain(childSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return constraints.constrain(_animatedSize!);
|
||||
}
|
||||
|
||||
void _restartAnimation() {
|
||||
_lastValue = 0.0;
|
||||
_controller.forward(from: 0.0);
|
||||
|
@ -1769,6 +1769,7 @@ abstract class RenderBox extends RenderObject {
|
||||
}
|
||||
|
||||
Map<BoxConstraints, Size>? _cachedDryLayoutSizes;
|
||||
bool _computingThisDryLayout = false;
|
||||
|
||||
/// Returns the [Size] that this [RenderBox] would like to be given the
|
||||
/// provided [BoxConstraints].
|
||||
@ -1800,9 +1801,24 @@ abstract class RenderBox extends RenderObject {
|
||||
}());
|
||||
if (shouldCache) {
|
||||
_cachedDryLayoutSizes ??= <BoxConstraints, Size>{};
|
||||
return _cachedDryLayoutSizes!.putIfAbsent(constraints, () => computeDryLayout(constraints));
|
||||
return _cachedDryLayoutSizes!.putIfAbsent(constraints, () => _computeDryLayout(constraints));
|
||||
}
|
||||
return computeDryLayout(constraints);
|
||||
return _computeDryLayout(constraints);
|
||||
}
|
||||
|
||||
Size _computeDryLayout(BoxConstraints constraints) {
|
||||
assert(() {
|
||||
assert(!_computingThisDryLayout);
|
||||
_computingThisDryLayout = true;
|
||||
return true;
|
||||
}());
|
||||
final Size result = computeDryLayout(constraints);
|
||||
assert(() {
|
||||
assert(_computingThisDryLayout);
|
||||
_computingThisDryLayout = false;
|
||||
return true;
|
||||
}());
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Computes the value returned by [getDryLayout]. Do not call this
|
||||
@ -1907,7 +1923,7 @@ abstract class RenderBox extends RenderObject {
|
||||
assert(_size._owner == this);
|
||||
if (RenderObject.debugActiveLayout != null) {
|
||||
assert(
|
||||
debugDoingThisResize || debugDoingThisLayout ||
|
||||
debugDoingThisResize || debugDoingThisLayout || _computingThisDryLayout ||
|
||||
(RenderObject.debugActiveLayout == parent && _size._canBeUsedByParent),
|
||||
'RenderBox.size accessed beyond the scope of resize, layout, or '
|
||||
'permitted parent access. RenderBox can always access its own size, '
|
||||
|
@ -315,5 +315,53 @@ void main() {
|
||||
expect(renderObject.clipBehavior, clip);
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('works wrapped in IntrinsicHeight and Wrap', (WidgetTester tester) async {
|
||||
Future<void> pumpWidget(Size size, [Duration? duration]) async {
|
||||
return tester.pumpWidget(
|
||||
Center(
|
||||
child: IntrinsicHeight(
|
||||
child: Wrap(
|
||||
textDirection: TextDirection.ltr,
|
||||
children: <Widget>[
|
||||
AnimatedSize(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.easeInOutBack,
|
||||
vsync: tester,
|
||||
child: SizedBox(
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
duration,
|
||||
);
|
||||
}
|
||||
|
||||
await pumpWidget(const Size(100, 100));
|
||||
expect(tester.renderObject<RenderBox>(find.byType(IntrinsicHeight)).size, const Size(100, 100));
|
||||
|
||||
await pumpWidget(const Size(150, 200));
|
||||
expect(tester.renderObject<RenderBox>(find.byType(IntrinsicHeight)).size, const Size(100, 100));
|
||||
|
||||
// Each pump triggers verification of dry layout.
|
||||
for (int total = 0; total < 200; total += 10) {
|
||||
await tester.pump(const Duration(milliseconds: 10));
|
||||
}
|
||||
expect(tester.renderObject<RenderBox>(find.byType(IntrinsicHeight)).size, const Size(150, 200));
|
||||
|
||||
// Change every pump
|
||||
await pumpWidget(const Size(100, 100));
|
||||
expect(tester.renderObject<RenderBox>(find.byType(IntrinsicHeight)).size, const Size(150, 200));
|
||||
|
||||
await pumpWidget(const Size(111, 111), const Duration(milliseconds: 10));
|
||||
expect(tester.renderObject<RenderBox>(find.byType(IntrinsicHeight)).size, const Size(111, 111));
|
||||
|
||||
await pumpWidget(const Size(222, 222), const Duration(milliseconds: 10));
|
||||
expect(tester.renderObject<RenderBox>(find.byType(IntrinsicHeight)).size, const Size(222, 222));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user