Commit 0e38cba9 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Make the limit that defines Row/Column free space configurable (#4646)

parent fad7cf59
...@@ -261,7 +261,7 @@ class IconWithText extends StatelessWidget { ...@@ -261,7 +261,7 @@ class IconWithText extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new Row( return new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new IconButton( new IconButton(
icon: new Icon(icon), icon: new Icon(icon),
...@@ -282,7 +282,7 @@ class MiniIconWithText extends StatelessWidget { ...@@ -282,7 +282,7 @@ class MiniIconWithText extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new Row( return new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new Padding( new Padding(
padding: new EdgeInsets.only(right: 8.0), padding: new EdgeInsets.only(right: 8.0),
......
...@@ -97,7 +97,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> { ...@@ -97,7 +97,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
return new Align( return new Align(
alignment: new FractionalOffset(0.5, 0.4), alignment: new FractionalOffset(0.5, 0.4),
child: new ButtonBar( child: new ButtonBar(
alignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new RaisedButton( new RaisedButton(
child: new Text('RAISED BUTTON'), child: new Text('RAISED BUTTON'),
...@@ -118,7 +118,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> { ...@@ -118,7 +118,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
return new Align( return new Align(
alignment: new FractionalOffset(0.5, 0.4), alignment: new FractionalOffset(0.5, 0.4),
child: new ButtonBar( child: new ButtonBar(
alignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new FlatButton( new FlatButton(
child: new Text('FLAT BUTTON'), child: new Text('FLAT BUTTON'),
...@@ -165,7 +165,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> { ...@@ -165,7 +165,7 @@ class _ButtonsDemoState extends State<ButtonsDemo> {
return new Align( return new Align(
alignment: new FractionalOffset(0.5, 0.4), alignment: new FractionalOffset(0.5, 0.4),
child: new Row( child: new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new IconButton( new IconButton(
icon: new Icon(Icons.thumb_up), icon: new Icon(Icons.thumb_up),
......
...@@ -80,10 +80,10 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> { ...@@ -80,10 +80,10 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> {
return new Align( return new Align(
alignment: new FractionalOffset(0.5, 0.4), alignment: new FractionalOffset(0.5, 0.4),
child: new Column( child: new Column(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new Row( new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new Checkbox(value: checkboxValueA, onChanged: (bool value) { new Checkbox(value: checkboxValueA, onChanged: (bool value) {
setState(() { setState(() {
...@@ -98,7 +98,7 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> { ...@@ -98,7 +98,7 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> {
] ]
), ),
new Row( new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
// Disabled checkboxes // Disabled checkboxes
new Checkbox(value: true, onChanged: null), new Checkbox(value: true, onChanged: null),
...@@ -114,10 +114,10 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> { ...@@ -114,10 +114,10 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> {
return new Align( return new Align(
alignment: new FractionalOffset(0.5, 0.4), alignment: new FractionalOffset(0.5, 0.4),
child: new Column( child: new Column(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new Row( new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new Radio<int>( new Radio<int>(
value: 0, value: 0,
...@@ -138,7 +138,7 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> { ...@@ -138,7 +138,7 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> {
), ),
// Disabled radio buttons // Disabled radio buttons
new Row( new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new Radio<int>( new Radio<int>(
value: 0, value: 0,
...@@ -166,7 +166,7 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> { ...@@ -166,7 +166,7 @@ class _SelectionControlsDemoState extends State<SelectionControlsDemo> {
return new Align( return new Align(
alignment: new FractionalOffset(0.5, 0.4), alignment: new FractionalOffset(0.5, 0.4),
child: new Row( child: new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new Switch(value: switchValue, onChanged: (bool value) { new Switch(value: switchValue, onChanged: (bool value) {
setState(() { setState(() {
......
...@@ -61,7 +61,7 @@ class StockSymbolView extends StatelessWidget { ...@@ -61,7 +61,7 @@ class StockSymbolView extends StatelessWidget {
) )
), ),
], ],
mainAxisAlignment: MainAxisAlignment.collapse mainAxisSize: MainAxisSize.min
) )
); );
} }
......
...@@ -29,12 +29,16 @@ class ButtonBar extends StatelessWidget { ...@@ -29,12 +29,16 @@ class ButtonBar extends StatelessWidget {
ButtonBar({ ButtonBar({
Key key, Key key,
this.alignment: MainAxisAlignment.end, this.alignment: MainAxisAlignment.end,
this.mainAxisSize: MainAxisSize.max,
this.children this.children
}) : super(key: key); }) : super(key: key);
/// How the children should be placed along the horizontal axis. /// How the children should be placed along the horizontal axis.
final MainAxisAlignment alignment; final MainAxisAlignment alignment;
/// How much horizontal space is available. See [Row.mainAxisSize].
final MainAxisSize mainAxisSize;
/// The buttons to arrange horizontally. /// The buttons to arrange horizontally.
/// ///
/// Typically [RaisedButton] or [FlatButton] widgets. /// Typically [RaisedButton] or [FlatButton] widgets.
...@@ -51,6 +55,7 @@ class ButtonBar extends StatelessWidget { ...@@ -51,6 +55,7 @@ class ButtonBar extends StatelessWidget {
), ),
child: new Row( child: new Row(
mainAxisAlignment: alignment, mainAxisAlignment: alignment,
mainAxisSize: mainAxisSize,
children: children.map/*<Widget>*/((Widget child) { children: children.map/*<Widget>*/((Widget child) {
return new Padding( return new Padding(
padding: new EdgeInsets.symmetric(horizontal: paddingUnit), padding: new EdgeInsets.symmetric(horizontal: paddingUnit),
......
...@@ -116,7 +116,7 @@ class Chip extends StatelessWidget { ...@@ -116,7 +116,7 @@ class Chip extends StatelessWidget {
), ),
child: new Row( child: new Row(
children: children, children: children,
mainAxisAlignment: MainAxisAlignment.collapse mainAxisSize: MainAxisSize.min
) )
) )
); );
......
...@@ -485,7 +485,8 @@ class _DropDownButtonState<T> extends State<DropDownButton<T>> { ...@@ -485,7 +485,8 @@ class _DropDownButtonState<T> extends State<DropDownButton<T>> {
Widget result = new DefaultTextStyle( Widget result = new DefaultTextStyle(
style: style, style: style,
child: new Row( child: new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[ children: <Widget>[
// We use an IndexedStack to make sure we have enough width to show any // We use an IndexedStack to make sure we have enough width to show any
// possible item as the selected item without changing size. // possible item as the selected item without changing size.
......
...@@ -169,7 +169,7 @@ class ListItem extends StatelessWidget { ...@@ -169,7 +169,7 @@ class ListItem extends StatelessWidget {
Widget center = primaryLine; Widget center = primaryLine;
if (subtitle != null && (isTwoLine || isThreeLine)) { if (subtitle != null && (isTwoLine || isThreeLine)) {
center = new Column( center = new Column(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
primaryLine, primaryLine,
......
...@@ -1207,7 +1207,7 @@ class TabPageSelector<T> extends StatelessWidget { ...@@ -1207,7 +1207,7 @@ class TabPageSelector<T> extends StatelessWidget {
label: 'Page ${selection.index + 1} of ${selection.values.length}', label: 'Page ${selection.index + 1} of ${selection.values.length}',
child: new Row( child: new Row(
children: selection.values.map((T tab) => _buildTabIndicator(selection, tab, animation, selectedColor, previousColor)).toList(), children: selection.values.map((T tab) => _buildTabIndicator(selection, tab, animation, selectedColor, previousColor)).toList(),
mainAxisAlignment: MainAxisAlignment.collapse mainAxisSize: MainAxisSize.min
) )
); );
} }
......
...@@ -44,7 +44,7 @@ class _TextSelectionToolbar extends StatelessWidget { ...@@ -44,7 +44,7 @@ class _TextSelectionToolbar extends StatelessWidget {
elevation: 1, elevation: 1,
child: new Container( child: new Container(
height: 44.0, height: 44.0,
child: new Row(mainAxisAlignment: MainAxisAlignment.collapse, children: items) child: new Row(mainAxisSize: MainAxisSize.min, children: items)
) )
); );
} }
......
...@@ -279,10 +279,10 @@ class _TimePickerHeader extends StatelessWidget { ...@@ -279,10 +279,10 @@ class _TimePickerHeader extends StatelessWidget {
onTap: _handleChangeDayPeriod, onTap: _handleChangeDayPeriod,
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
child: new Column( child: new Column(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new Text('AM', style: amStyle), new Text('AM', style: amStyle),
new Container(width: 0.0, height: 8.0), // Vertical spsacer new Container(width: 0.0, height: 8.0), // Vertical spacer
new Text('PM', style: pmStyle), new Text('PM', style: pmStyle),
] ]
) )
......
...@@ -29,6 +29,19 @@ enum FlexDirection { ...@@ -29,6 +29,19 @@ enum FlexDirection {
vertical vertical
} }
/// The incoming constraint parameter that defines how much space is available
/// along the main axis in a flex layout. Flex layouts allocate the difference
/// between the available space and the sum of the sizes of the children
/// which are not flexible to the layout's flexible children and the space
/// around the children. See [Row], [Column], [MainAxisAlignment], [Flexible].
enum MainAxisSize {
/// The available space is defined by the incoming constraint's min parameter.
min,
/// The available space is defined by the incoming constraint's max parameter.
max,
}
/// How the children should be placed along the main axis in a flex layout. /// How the children should be placed along the main axis in a flex layout.
enum MainAxisAlignment { enum MainAxisAlignment {
/// Place the children as close to the start of the main axis as possible. /// Place the children as close to the start of the main axis as possible.
...@@ -47,10 +60,7 @@ enum MainAxisAlignment { ...@@ -47,10 +60,7 @@ enum MainAxisAlignment {
spaceAround, spaceAround,
/// Place the free space evenly between the children as well as before and after the first and last child. /// Place the free space evenly between the children as well as before and after the first and last child.
spaceEvenly, spaceEvenly
/// Do not expand to fill the free space. None of the children may specify a flex factor.
collapse,
} }
/// How the children should be placed along the cross axis in a flex layout. /// How the children should be placed along the cross axis in a flex layout.
...@@ -97,11 +107,13 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -97,11 +107,13 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
RenderFlex({ RenderFlex({
List<RenderBox> children, List<RenderBox> children,
FlexDirection direction: FlexDirection.horizontal, FlexDirection direction: FlexDirection.horizontal,
MainAxisSize mainAxisSize: MainAxisSize.max,
MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start,
CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
TextBaseline textBaseline TextBaseline textBaseline
}) : _direction = direction, }) : _direction = direction,
_mainAxisAlignment = mainAxisAlignment, _mainAxisAlignment = mainAxisAlignment,
_mainAxisSize = mainAxisSize,
_crossAxisAlignment = crossAxisAlignment, _crossAxisAlignment = crossAxisAlignment,
_textBaseline = textBaseline { _textBaseline = textBaseline {
addAll(children); addAll(children);
...@@ -121,12 +133,23 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -121,12 +133,23 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
MainAxisAlignment get mainAxisAlignment => _mainAxisAlignment; MainAxisAlignment get mainAxisAlignment => _mainAxisAlignment;
MainAxisAlignment _mainAxisAlignment; MainAxisAlignment _mainAxisAlignment;
set mainAxisAlignment (MainAxisAlignment value) { set mainAxisAlignment (MainAxisAlignment value) {
assert(value != null);
if (_mainAxisAlignment != value) { if (_mainAxisAlignment != value) {
_mainAxisAlignment = value; _mainAxisAlignment = value;
markNeedsLayout(); markNeedsLayout();
} }
} }
/// The limit used to compute free space along the main axis.
MainAxisSize get mainAxisSize => _mainAxisSize;
MainAxisSize _mainAxisSize;
set mainAxisSize (MainAxisSize value) {
if (_mainAxisSize != value) {
_mainAxisSize = value;
markNeedsLayout();
}
}
/// How the children should be placed along the cross axis. /// How the children should be placed along the cross axis.
CrossAxisAlignment get crossAxisAlignment => _crossAxisAlignment; CrossAxisAlignment get crossAxisAlignment => _crossAxisAlignment;
CrossAxisAlignment _crossAxisAlignment; CrossAxisAlignment _crossAxisAlignment;
...@@ -299,10 +322,14 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -299,10 +322,14 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
int totalFlex = 0; int totalFlex = 0;
int totalChildren = 0; int totalChildren = 0;
assert(constraints != null); assert(constraints != null);
final double mainSize = (_direction == FlexDirection.horizontal) ? constraints.constrainWidth() : constraints.constrainHeight(); final bool isHorizontal = _direction == FlexDirection.horizontal;
final bool canFlex = mainSize < double.INFINITY && mainAxisAlignment != MainAxisAlignment.collapse; final double minMainSize = isHorizontal ? constraints.minWidth : constraints.minHeight;
double crossSize = 0.0; // This is determined as we lay out the children final double maxMainSize = isHorizontal ? constraints.maxWidth : constraints.maxHeight;
double freeSpace = canFlex ? mainSize : 0.0; final double availableSize = mainAxisSize == MainAxisSize.max ? maxMainSize : minMainSize;
final bool canFlex = availableSize < double.INFINITY;
double crossSize = 0.0;
double allocatedSize = 0.0; // Sum of the sizes of the the non-flexible children.
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
final FlexParentData childParentData = child.parentData; final FlexParentData childParentData = child.parentData;
...@@ -315,12 +342,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -315,12 +342,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
final String dimension = _direction == FlexDirection.horizontal ? 'width' : 'height'; final String dimension = _direction == FlexDirection.horizontal ? 'width' : 'height';
String error, message; String error, message;
String addendum = ''; String addendum = '';
if (mainAxisAlignment == MainAxisAlignment.collapse) { if (availableSize == double.INFINITY) {
error = 'RenderFlex children have non-zero flex but mainAxisAlignment is set to "collapse".';
message = 'The MainAxisAlignment.collapse value indicates that the $identity is to shrink-wrap its children '
'along the $axis axis. Setting a flex on a child (e.g. using a Flexible) indicates that the '
'child is to expand to fill the remaining space in the $axis direction.';
} else if (mainSize == double.INFINITY) {
error = 'RenderFlex children have non-zero flex but incoming $dimension constraints are unbounded.'; error = 'RenderFlex children have non-zero flex but incoming $dimension constraints are unbounded.';
message = 'When a $identity is in a parent that does not provide a finite $dimension constraint, for example ' message = 'When a $identity is in a parent that does not provide a finite $dimension constraint, for example '
'if it is in a $axis scrollable, it will try to shrink-wrap its children along the $axis ' 'if it is in a $axis scrollable, it will try to shrink-wrap its children along the $axis '
...@@ -397,16 +419,16 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -397,16 +419,16 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
} }
} }
child.layout(innerConstraints, parentUsesSize: true); child.layout(innerConstraints, parentUsesSize: true);
freeSpace -= _getMainSize(child); allocatedSize += _getMainSize(child);
crossSize = math.max(crossSize, _getCrossSize(child)); crossSize = math.max(crossSize, _getCrossSize(child));
} }
assert(child.parentData == childParentData); assert(child.parentData == childParentData);
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
_overflow = math.max(0.0, -freeSpace); _overflow = math.max(0.0, allocatedSize - (canFlex ? maxMainSize : 0.0));
freeSpace = math.max(0.0, freeSpace);
// Distribute remaining space to flexible children, and determine baseline. // Distribute free space to flexible children, and determine baseline.
double freeSpace = math.max(0.0, (canFlex ? availableSize : 0.0) - allocatedSize);
double maxBaselineDistance = 0.0; double maxBaselineDistance = 0.0;
double usedSpace = 0.0; double usedSpace = 0.0;
if (totalFlex > 0 || crossAxisAlignment == CrossAxisAlignment.baseline) { if (totalFlex > 0 || crossAxisAlignment == CrossAxisAlignment.baseline) {
...@@ -470,20 +492,23 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -470,20 +492,23 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
double betweenSpace; double betweenSpace;
double remainingSpace; double remainingSpace;
if (canFlex) { if (canFlex) {
final bool isMainAxisSizeMax = mainAxisSize == MainAxisSize.max;
final double preferredSize = isMainAxisSizeMax ? maxMainSize : allocatedSize;
remainingSpace = math.max(0.0, freeSpace - usedSpace); remainingSpace = math.max(0.0, freeSpace - usedSpace);
switch (_direction) { switch (_direction) {
case FlexDirection.horizontal: case FlexDirection.horizontal:
size = constraints.constrain(new Size(mainSize, crossSize)); size = constraints.constrain(new Size(preferredSize, crossSize));
crossSize = size.height; crossSize = size.height;
assert(size.width == mainSize); assert(isMainAxisSizeMax ? size.width == maxMainSize : size.width >= minMainSize);
break; break;
case FlexDirection.vertical: case FlexDirection.vertical:
size = constraints.constrain(new Size(crossSize, mainSize)); size = constraints.constrain(new Size(crossSize, preferredSize));
crossSize = size.width; crossSize = size.width;
assert(size.height == mainSize); assert(isMainAxisSizeMax ? size.height == maxMainSize : size.height >= minMainSize);
break; break;
} }
} else { } else {
assert(mainAxisSize == MainAxisSize.max);
leadingSpace = 0.0; leadingSpace = 0.0;
betweenSpace = 0.0; betweenSpace = 0.0;
switch (_direction) { switch (_direction) {
...@@ -502,7 +527,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -502,7 +527,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
} }
switch (_mainAxisAlignment) { switch (_mainAxisAlignment) {
case MainAxisAlignment.start: case MainAxisAlignment.start:
case MainAxisAlignment.collapse:
leadingSpace = 0.0; leadingSpace = 0.0;
betweenSpace = 0.0; betweenSpace = 0.0;
break; break;
...@@ -632,6 +656,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -632,6 +656,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
super.debugFillDescription(description); super.debugFillDescription(description);
description.add('direction: $_direction'); description.add('direction: $_direction');
description.add('mainAxisAlignment: $_mainAxisAlignment'); description.add('mainAxisAlignment: $_mainAxisAlignment');
description.add('mainAxisSize: $_mainAxisSize');
description.add('crossAxisAlignment: $_crossAxisAlignment'); description.add('crossAxisAlignment: $_crossAxisAlignment');
description.add('textBaseline: $_textBaseline'); description.add('textBaseline: $_textBaseline');
} }
......
...@@ -29,6 +29,7 @@ export 'package:flutter/rendering.dart' show ...@@ -29,6 +29,7 @@ export 'package:flutter/rendering.dart' show
GridSpecification, GridSpecification,
HitTestBehavior, HitTestBehavior,
MainAxisAlignment, MainAxisAlignment,
MainAxisSize,
MaxTileWidthGridDelegate, MaxTileWidthGridDelegate,
MultiChildLayoutDelegate, MultiChildLayoutDelegate,
PaintingContext, PaintingContext,
...@@ -1778,12 +1779,14 @@ class Flex extends MultiChildRenderObjectWidget { ...@@ -1778,12 +1779,14 @@ class Flex extends MultiChildRenderObjectWidget {
Key key, Key key,
this.direction: FlexDirection.horizontal, this.direction: FlexDirection.horizontal,
this.mainAxisAlignment: MainAxisAlignment.start, this.mainAxisAlignment: MainAxisAlignment.start,
this.mainAxisSize: MainAxisSize.max,
this.crossAxisAlignment: CrossAxisAlignment.center, this.crossAxisAlignment: CrossAxisAlignment.center,
this.textBaseline, this.textBaseline,
List<Widget> children: _emptyWidgetList List<Widget> children: _emptyWidgetList
}) : super(key: key, children: children) { }) : super(key: key, children: children) {
assert(direction != null); assert(direction != null);
assert(mainAxisAlignment != null); assert(mainAxisAlignment != null);
assert(mainAxisSize != null);
assert(crossAxisAlignment != null); assert(crossAxisAlignment != null);
assert(crossAxisAlignment != CrossAxisAlignment.baseline || textBaseline != null); assert(crossAxisAlignment != CrossAxisAlignment.baseline || textBaseline != null);
} }
...@@ -1794,6 +1797,17 @@ class Flex extends MultiChildRenderObjectWidget { ...@@ -1794,6 +1797,17 @@ class Flex extends MultiChildRenderObjectWidget {
/// How the children should be placed along the main axis. /// How the children should be placed along the main axis.
final MainAxisAlignment mainAxisAlignment; final MainAxisAlignment mainAxisAlignment;
/// The limit that defines how much space is available along the main axis.
///
/// By default the size of this widget will be as big as the incoming
/// max constraint. In other words it will become as big as possible
/// along its main axis by growing [Flexible] children and inserting
/// space between children per the [mainAxisAlignment] parameter.
/// If mainAxisSize is [MainAxisSize.min] then this widget's size along
/// the main axis will be as small as possible. This version of the layout
/// is sometimes referred to as "shrink wrapping".
final MainAxisSize mainAxisSize;
/// How the children should be placed along the cross axis. /// How the children should be placed along the cross axis.
final CrossAxisAlignment crossAxisAlignment; final CrossAxisAlignment crossAxisAlignment;
...@@ -1801,13 +1815,22 @@ class Flex extends MultiChildRenderObjectWidget { ...@@ -1801,13 +1815,22 @@ class Flex extends MultiChildRenderObjectWidget {
final TextBaseline textBaseline; final TextBaseline textBaseline;
@override @override
RenderFlex createRenderObject(BuildContext context) => new RenderFlex(direction: direction, mainAxisAlignment: mainAxisAlignment, crossAxisAlignment: crossAxisAlignment, textBaseline: textBaseline); RenderFlex createRenderObject(BuildContext context) {
return new RenderFlex(
direction: direction,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textBaseline: textBaseline
);
}
@override @override
void updateRenderObject(BuildContext context, RenderFlex renderObject) { void updateRenderObject(BuildContext context, RenderFlex renderObject) {
renderObject renderObject
..direction = direction ..direction = direction
..mainAxisAlignment = mainAxisAlignment ..mainAxisAlignment = mainAxisAlignment
..mainAxisSize = mainAxisSize
..crossAxisAlignment = crossAxisAlignment ..crossAxisAlignment = crossAxisAlignment
..textBaseline = textBaseline; ..textBaseline = textBaseline;
} }
...@@ -1820,12 +1843,13 @@ class Flex extends MultiChildRenderObjectWidget { ...@@ -1820,12 +1843,13 @@ class Flex extends MultiChildRenderObjectWidget {
class Row extends Flex { class Row extends Flex {
/// Creates a horizontal array of children. /// Creates a horizontal array of children.
/// ///
/// The [direction], [mainAxisAlignment], and [crossAxisAlignment] arguments /// The [direction], [mainAxisAlignment], [mainAxisSize], and
/// must not be null. If [crossAxisAlignment] is /// [crossAxisAlignment] arguments must not be null. If [crossAxisAlignment]
/// [CrossAxisAlignment.baseline], then [textBaseline] must not be null. /// is [CrossAxisAlignment.baseline], then [textBaseline] must not be null.
Row({ Row({
Key key, Key key,
MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start,
MainAxisSize mainAxisSize: MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
TextBaseline textBaseline, TextBaseline textBaseline,
List<Widget> children: _emptyWidgetList List<Widget> children: _emptyWidgetList
...@@ -1834,6 +1858,7 @@ class Row extends Flex { ...@@ -1834,6 +1858,7 @@ class Row extends Flex {
key: key, key: key,
direction: FlexDirection.horizontal, direction: FlexDirection.horizontal,
mainAxisAlignment: mainAxisAlignment, mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment, crossAxisAlignment: crossAxisAlignment,
textBaseline: textBaseline textBaseline: textBaseline
); );
...@@ -1846,12 +1871,13 @@ class Row extends Flex { ...@@ -1846,12 +1871,13 @@ class Row extends Flex {
class Column extends Flex { class Column extends Flex {
/// Creates a vertical array of children. /// Creates a vertical array of children.
/// ///
/// The [direction], [mainAxisAlignment], and [crossAxisAlignment] arguments /// The [direction], [mainAxisAlignment], [mainAxisSize], and
/// must not be null. If [crossAxisAlignment] is /// [crossAxisAlignment] arguments must not be null. If [crossAxisAlignment]
/// [CrossAxisAlignment.baseline], then [textBaseline] must not be null. /// is [CrossAxisAlignment.baseline], then [textBaseline] must not be null.
Column({ Column({
Key key, Key key,
MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start,
MainAxisSize mainAxisSize: MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
TextBaseline textBaseline, TextBaseline textBaseline,
List<Widget> children: _emptyWidgetList List<Widget> children: _emptyWidgetList
...@@ -1860,6 +1886,7 @@ class Column extends Flex { ...@@ -1860,6 +1886,7 @@ class Column extends Flex {
key: key, key: key,
direction: FlexDirection.vertical, direction: FlexDirection.vertical,
mainAxisAlignment: mainAxisAlignment, mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment, crossAxisAlignment: crossAxisAlignment,
textBaseline: textBaseline textBaseline: textBaseline
); );
......
This diff is collapsed.
...@@ -47,116 +47,4 @@ void main() { ...@@ -47,116 +47,4 @@ void main() {
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
expect(didReceiveTap, isTrue); expect(didReceiveTap, isTrue);
}); });
testWidgets('Row and FlexJustifyContent.collapse', (WidgetTester tester) async {
final Key flexKey = new Key('flexKey');
// Row without mainAxisAlignment: FlexJustifyContent.collapse
await tester.pumpWidget(new Center(
child: new Row(
children: <Widget>[
new Container(width: 10.0, height: 100.0),
new Container(width: 30.0, height: 100.0)
],
key: flexKey
)
));
RenderBox renderBox = tester.renderObject(find.byKey(flexKey));
expect(renderBox.size.width, equals(800.0));
expect(renderBox.size.height, equals(100.0));
// Row with mainAxisAlignment: FlexJustifyContent.collapse
await tester.pumpWidget(new Center(
child: new Row(
children: <Widget>[
new Container(width: 10.0, height: 100.0),
new Container(width: 30.0, height: 100.0)
],
key: flexKey,
mainAxisAlignment: MainAxisAlignment.collapse
)
));
renderBox = tester.renderObject(find.byKey(flexKey));
expect(renderBox.size.width, equals(40.0));
expect(renderBox.size.height, equals(100.0));
});
testWidgets('Column and FlexJustifyContent.collapse', (WidgetTester tester) async {
final Key flexKey = new Key('flexKey');
// Column without mainAxisAlignment: FlexJustifyContent.collapse
await tester.pumpWidget(new Center(
child: new Column(
children: <Widget>[
new Container(width: 100.0, height: 100.0),
new Container(width: 100.0, height: 150.0)
],
key: flexKey
)
));
RenderBox renderBox = tester.renderObject(find.byKey(flexKey));
expect(renderBox.size.width, equals(100.0));
expect(renderBox.size.height, equals(600.0));
// Column with mainAxisAlignment: FlexJustifyContent.collapse
await tester.pumpWidget(new Center(
child: new Column(
children: <Widget>[
new Container(width: 100.0, height: 100.0),
new Container(width: 100.0, height: 150.0)
],
key: flexKey,
mainAxisAlignment: MainAxisAlignment.collapse
)
));
renderBox = tester.renderObject(find.byKey(flexKey));
expect(renderBox.size.width, equals(100.0));
expect(renderBox.size.height, equals(250.0));
});
testWidgets('Can layout at zero size', (WidgetTester tester) async {
final Key childKey = new Key('childKey');
await tester.pumpWidget(new Center(
child: new Container(
width: 0.0,
height: 0.0,
child: new Column(
children: <Widget>[
new Container(
key: childKey,
width: 100.0,
height: 100.0
)
],
mainAxisAlignment: MainAxisAlignment.collapse
)
)
));
RenderBox renderBox = tester.renderObject(find.byKey(childKey));
expect(renderBox.size.width, equals(0.0));
expect(renderBox.size.height, equals(100.0));
await tester.pumpWidget(new Center(
child: new Container(
width: 0.0,
height: 0.0,
child: new Row(
children: <Widget>[
new Container(
key: childKey,
width: 100.0,
height: 100.0
)
],
mainAxisAlignment: MainAxisAlignment.collapse
)
)
));
renderBox = tester.renderObject(find.byKey(childKey));
expect(renderBox.size.width, equals(100.0));
expect(renderBox.size.height, equals(0.0));
});
} }
...@@ -16,7 +16,7 @@ void main() { ...@@ -16,7 +16,7 @@ void main() {
key: rotatedBoxKey, key: rotatedBoxKey,
quarterTurns: 1, quarterTurns: 1,
child: new Row( child: new Row(
mainAxisAlignment: MainAxisAlignment.collapse, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
new GestureDetector( new GestureDetector(
onTap: () { log.add('left'); }, onTap: () { log.add('left'); },
......
This diff is collapsed.
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