diff --git a/packages/flutter/lib/rendering/block.dart b/packages/flutter/lib/rendering/block.dart index d5f3497e34..7214c533d7 100644 --- a/packages/flutter/lib/rendering/block.dart +++ b/packages/flutter/lib/rendering/block.dart @@ -49,6 +49,16 @@ abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin return new BoxConstraints.tightFor(height: constraints.constrainHeight(constraints.maxHeight)); } + double get _mainAxisExtent { + RenderBox child = lastChild; + if (child == null) + return 0.0; + BoxParentData parentData = child.parentData; + return _isVertical ? + parentData.position.y + child.size.height : + parentData.position.x + child.size.width; + } + void performLayout() { BoxConstraints innerConstraints = _getInnerConstraints(constraints); double position = 0.0; @@ -60,6 +70,10 @@ abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin position += _isVertical ? child.size.height : child.size.width; child = child.parentData.nextSibling; } + size = _isVertical ? + constraints.constrain(new Size(constraints.maxWidth, _mainAxisExtent)) : + constraints.constrain(new Size(_mainAxisExtent, constraints.maxHeight)); + assert(!size.isInfinite); } } @@ -137,23 +151,11 @@ class RenderBlock extends RenderBlockBase { return defaultComputeDistanceToFirstActualBaseline(baseline); } - double get _mainAxisExtent { - RenderBox child = lastChild; - if (child == null) - return 0.0; - BoxParentData parentData = child.parentData; - return _isVertical ? - parentData.position.y + child.size.height : - parentData.position.x + child.size.width; - } - void performLayout() { - assert(_isVertical ? constraints.maxHeight >= double.INFINITY : constraints.maxWidth >= double.INFINITY); + assert((_isVertical ? constraints.maxHeight >= double.INFINITY : constraints.maxWidth >= double.INFINITY) && + 'RenderBlock does not clip or resize its children, so it must be placed in a parent that does not constrain ' + + 'the block\'s main direction. You probably want to put the RenderBlock inside a RenderViewport.' is String); super.performLayout(); - size = _isVertical ? - constraints.constrain(new Size(constraints.maxWidth, _mainAxisExtent)) : - constraints.constrain(new Size(_mainAxisExtent, constraints.maxHeight)); - assert(!size.isInfinite); } void paint(PaintingContext context, Offset offset) { @@ -168,9 +170,6 @@ class RenderBlock extends RenderBlockBase { class RenderBlockViewport extends RenderBlockBase { - // sizes itself to the given constraints - // at the start of layout, calls callback - RenderBlockViewport({ LayoutCallback callback, List children, @@ -200,20 +199,30 @@ class RenderBlockViewport extends RenderBlockBase { markNeedsPaint(); } + double _noIntrinsicDimensions() { + assert(() { + 'RenderBlockViewport does not support returning intrinsic dimensions. ' + + 'Calculating the intrinsic dimensions would require walking the entire child list, ' + + 'which defeats the entire point of having a lazily-built list of children.'; + return false; + }); + return 0.0; + } + double getMinIntrinsicWidth(BoxConstraints constraints) { - return constraints.constrainWidth(); + return _noIntrinsicDimensions(); } double getMaxIntrinsicWidth(BoxConstraints constraints) { - return constraints.constrainWidth(); + return _noIntrinsicDimensions(); } double getMinIntrinsicHeight(BoxConstraints constraints) { - return constraints.constrainHeight(); + return _noIntrinsicDimensions(); } double getMaxIntrinsicHeight(BoxConstraints constraints) { - return constraints.constrainHeight(); + return _noIntrinsicDimensions(); } // We don't override computeDistanceToActualBaseline(), because we @@ -221,16 +230,8 @@ class RenderBlockViewport extends RenderBlockBase { // scroll the RenderBlockViewport, it would shift in its parent if // the parent was baseline-aligned, which makes no sense. - bool get sizedByParent => true; - - void performResize() { - size = constraints.biggest; - assert(!size.isInfinite); - } - bool get debugDoesLayoutWithCallback => true; void performLayout() { - assert(constraints.maxHeight < double.INFINITY); if (_callback != null) { try { _inCallback = true; diff --git a/packages/flutter/lib/widgets/mixed_viewport.dart b/packages/flutter/lib/widgets/mixed_viewport.dart index 3b8ce4f1f9..c8e58c486a 100644 --- a/packages/flutter/lib/widgets/mixed_viewport.dart +++ b/packages/flutter/lib/widgets/mixed_viewport.dart @@ -78,7 +78,7 @@ class MixedViewportLayoutState { } class MixedViewport extends RenderObjectWrapper { - MixedViewport({ this.builder, this.startOffset, this.token, this.layoutState, Key key }) + MixedViewport({ Key key, this.builder, this.startOffset, this.token, this.layoutState }) : super(key: key) { assert(this.layoutState != null); } @@ -258,7 +258,11 @@ class MixedViewport extends RenderObjectWrapper { final List offsets = layoutState._childOffsets; final Map<_Key, Widget> childrenByKey = layoutState._childrenByKey; - final double height = renderObject.size.height; + final double height = constraints.maxHeight; + assert(height < double.INFINITY && + 'There is no point putting a lazily-built MixedViewport inside a box with infinite internal height ' + + '(e.g. inside something that scrolls), because it would then just eagerly build all the children. ' + + 'You probably want to put the MixedViewport inside a container with a fixed height.' is String); final double endOffset = startOffset + height; BoxConstraints innerConstraints = new BoxConstraints.tightFor(width: constraints.constrainWidth());