From 0e38cba95f4a3094c7d27be3099863b2e8954bc6 Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Tue, 21 Jun 2016 14:29:22 -0700 Subject: [PATCH] Make the limit that defines Row/Column free space configurable (#4646) --- dev/benchmarks/complex_layout/lib/main.dart | 4 +- .../lib/demo/buttons_demo.dart | 6 +- .../lib/demo/selection_controls_demo.dart | 14 +- examples/stocks/lib/stock_symbol_viewer.dart | 2 +- .../flutter/lib/src/material/button_bar.dart | 5 + packages/flutter/lib/src/material/chip.dart | 2 +- .../flutter/lib/src/material/drop_down.dart | 3 +- .../flutter/lib/src/material/list_item.dart | 2 +- packages/flutter/lib/src/material/tabs.dart | 2 +- .../lib/src/material/text_selection.dart | 2 +- .../flutter/lib/src/material/time_picker.dart | 4 +- packages/flutter/lib/src/rendering/flex.dart | 71 +++- packages/flutter/lib/src/widgets/basic.dart | 41 +- packages/flutter/test/widget/column_test.dart | 389 +++++++++++++++++ packages/flutter/test/widget/flex_test.dart | 112 ----- .../flutter/test/widget/rotated_box_test.dart | 2 +- packages/flutter/test/widget/row_test.dart | 394 ++++++++++++++++++ 17 files changed, 892 insertions(+), 163 deletions(-) create mode 100644 packages/flutter/test/widget/column_test.dart create mode 100644 packages/flutter/test/widget/row_test.dart diff --git a/dev/benchmarks/complex_layout/lib/main.dart b/dev/benchmarks/complex_layout/lib/main.dart index 7bee1d03760..72358dbd4c1 100644 --- a/dev/benchmarks/complex_layout/lib/main.dart +++ b/dev/benchmarks/complex_layout/lib/main.dart @@ -261,7 +261,7 @@ class IconWithText extends StatelessWidget { @override Widget build(BuildContext context) { return new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new IconButton( icon: new Icon(icon), @@ -282,7 +282,7 @@ class MiniIconWithText extends StatelessWidget { @override Widget build(BuildContext context) { return new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new Padding( padding: new EdgeInsets.only(right: 8.0), diff --git a/examples/flutter_gallery/lib/demo/buttons_demo.dart b/examples/flutter_gallery/lib/demo/buttons_demo.dart index d3d1fce68ee..1c7ba3b02ef 100644 --- a/examples/flutter_gallery/lib/demo/buttons_demo.dart +++ b/examples/flutter_gallery/lib/demo/buttons_demo.dart @@ -97,7 +97,7 @@ class _ButtonsDemoState extends State { return new Align( alignment: new FractionalOffset(0.5, 0.4), child: new ButtonBar( - alignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new RaisedButton( child: new Text('RAISED BUTTON'), @@ -118,7 +118,7 @@ class _ButtonsDemoState extends State { return new Align( alignment: new FractionalOffset(0.5, 0.4), child: new ButtonBar( - alignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new FlatButton( child: new Text('FLAT BUTTON'), @@ -165,7 +165,7 @@ class _ButtonsDemoState extends State { return new Align( alignment: new FractionalOffset(0.5, 0.4), child: new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new IconButton( icon: new Icon(Icons.thumb_up), diff --git a/examples/flutter_gallery/lib/demo/selection_controls_demo.dart b/examples/flutter_gallery/lib/demo/selection_controls_demo.dart index e79e229f650..a3d4e74bb6d 100644 --- a/examples/flutter_gallery/lib/demo/selection_controls_demo.dart +++ b/examples/flutter_gallery/lib/demo/selection_controls_demo.dart @@ -80,10 +80,10 @@ class _SelectionControlsDemoState extends State { return new Align( alignment: new FractionalOffset(0.5, 0.4), child: new Column( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new Checkbox(value: checkboxValueA, onChanged: (bool value) { setState(() { @@ -98,7 +98,7 @@ class _SelectionControlsDemoState extends State { ] ), new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ // Disabled checkboxes new Checkbox(value: true, onChanged: null), @@ -114,10 +114,10 @@ class _SelectionControlsDemoState extends State { return new Align( alignment: new FractionalOffset(0.5, 0.4), child: new Column( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new Radio( value: 0, @@ -138,7 +138,7 @@ class _SelectionControlsDemoState extends State { ), // Disabled radio buttons new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new Radio( value: 0, @@ -166,7 +166,7 @@ class _SelectionControlsDemoState extends State { return new Align( alignment: new FractionalOffset(0.5, 0.4), child: new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new Switch(value: switchValue, onChanged: (bool value) { setState(() { diff --git a/examples/stocks/lib/stock_symbol_viewer.dart b/examples/stocks/lib/stock_symbol_viewer.dart index 4af800bfc2d..3dbbd468849 100644 --- a/examples/stocks/lib/stock_symbol_viewer.dart +++ b/examples/stocks/lib/stock_symbol_viewer.dart @@ -61,7 +61,7 @@ class StockSymbolView extends StatelessWidget { ) ), ], - mainAxisAlignment: MainAxisAlignment.collapse + mainAxisSize: MainAxisSize.min ) ); } diff --git a/packages/flutter/lib/src/material/button_bar.dart b/packages/flutter/lib/src/material/button_bar.dart index d3d1a185e06..710c7ed0f34 100644 --- a/packages/flutter/lib/src/material/button_bar.dart +++ b/packages/flutter/lib/src/material/button_bar.dart @@ -29,12 +29,16 @@ class ButtonBar extends StatelessWidget { ButtonBar({ Key key, this.alignment: MainAxisAlignment.end, + this.mainAxisSize: MainAxisSize.max, this.children }) : super(key: key); /// How the children should be placed along the horizontal axis. final MainAxisAlignment alignment; + /// How much horizontal space is available. See [Row.mainAxisSize]. + final MainAxisSize mainAxisSize; + /// The buttons to arrange horizontally. /// /// Typically [RaisedButton] or [FlatButton] widgets. @@ -51,6 +55,7 @@ class ButtonBar extends StatelessWidget { ), child: new Row( mainAxisAlignment: alignment, + mainAxisSize: mainAxisSize, children: children.map/**/((Widget child) { return new Padding( padding: new EdgeInsets.symmetric(horizontal: paddingUnit), diff --git a/packages/flutter/lib/src/material/chip.dart b/packages/flutter/lib/src/material/chip.dart index 34b4f2ad037..fd509e9d5e6 100644 --- a/packages/flutter/lib/src/material/chip.dart +++ b/packages/flutter/lib/src/material/chip.dart @@ -116,7 +116,7 @@ class Chip extends StatelessWidget { ), child: new Row( children: children, - mainAxisAlignment: MainAxisAlignment.collapse + mainAxisSize: MainAxisSize.min ) ) ); diff --git a/packages/flutter/lib/src/material/drop_down.dart b/packages/flutter/lib/src/material/drop_down.dart index 18a9b2d1148..f0f1174fbac 100644 --- a/packages/flutter/lib/src/material/drop_down.dart +++ b/packages/flutter/lib/src/material/drop_down.dart @@ -485,7 +485,8 @@ class _DropDownButtonState extends State> { Widget result = new DefaultTextStyle( style: style, child: new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // We use an IndexedStack to make sure we have enough width to show any // possible item as the selected item without changing size. diff --git a/packages/flutter/lib/src/material/list_item.dart b/packages/flutter/lib/src/material/list_item.dart index e1fc13e1083..94258a47d9a 100644 --- a/packages/flutter/lib/src/material/list_item.dart +++ b/packages/flutter/lib/src/material/list_item.dart @@ -169,7 +169,7 @@ class ListItem extends StatelessWidget { Widget center = primaryLine; if (subtitle != null && (isTwoLine || isThreeLine)) { center = new Column( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ primaryLine, diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index 02c3efdcece..042a9f88083 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -1207,7 +1207,7 @@ class TabPageSelector extends StatelessWidget { label: 'Page ${selection.index + 1} of ${selection.values.length}', child: new Row( children: selection.values.map((T tab) => _buildTabIndicator(selection, tab, animation, selectedColor, previousColor)).toList(), - mainAxisAlignment: MainAxisAlignment.collapse + mainAxisSize: MainAxisSize.min ) ); } diff --git a/packages/flutter/lib/src/material/text_selection.dart b/packages/flutter/lib/src/material/text_selection.dart index fdeae03dbd4..eb3e820223d 100644 --- a/packages/flutter/lib/src/material/text_selection.dart +++ b/packages/flutter/lib/src/material/text_selection.dart @@ -44,7 +44,7 @@ class _TextSelectionToolbar extends StatelessWidget { elevation: 1, child: new Container( height: 44.0, - child: new Row(mainAxisAlignment: MainAxisAlignment.collapse, children: items) + child: new Row(mainAxisSize: MainAxisSize.min, children: items) ) ); } diff --git a/packages/flutter/lib/src/material/time_picker.dart b/packages/flutter/lib/src/material/time_picker.dart index 3f42dde9555..0f1b0afbae1 100644 --- a/packages/flutter/lib/src/material/time_picker.dart +++ b/packages/flutter/lib/src/material/time_picker.dart @@ -279,10 +279,10 @@ class _TimePickerHeader extends StatelessWidget { onTap: _handleChangeDayPeriod, behavior: HitTestBehavior.opaque, child: new Column( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ 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), ] ) diff --git a/packages/flutter/lib/src/rendering/flex.dart b/packages/flutter/lib/src/rendering/flex.dart index a1d33b26f27..dcf0e4fbd07 100644 --- a/packages/flutter/lib/src/rendering/flex.dart +++ b/packages/flutter/lib/src/rendering/flex.dart @@ -29,6 +29,19 @@ enum FlexDirection { 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. enum MainAxisAlignment { /// Place the children as close to the start of the main axis as possible. @@ -47,10 +60,7 @@ enum MainAxisAlignment { spaceAround, /// Place the free space evenly between the children as well as before and after the first and last child. - spaceEvenly, - - /// Do not expand to fill the free space. None of the children may specify a flex factor. - collapse, + spaceEvenly } /// How the children should be placed along the cross axis in a flex layout. @@ -97,11 +107,13 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin children, FlexDirection direction: FlexDirection.horizontal, + MainAxisSize mainAxisSize: MainAxisSize.max, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, TextBaseline textBaseline }) : _direction = direction, _mainAxisAlignment = mainAxisAlignment, + _mainAxisSize = mainAxisSize, _crossAxisAlignment = crossAxisAlignment, _textBaseline = textBaseline { addAll(children); @@ -121,12 +133,23 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin _mainAxisAlignment; MainAxisAlignment _mainAxisAlignment; set mainAxisAlignment (MainAxisAlignment value) { + assert(value != null); if (_mainAxisAlignment != value) { _mainAxisAlignment = value; 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. CrossAxisAlignment get crossAxisAlignment => _crossAxisAlignment; CrossAxisAlignment _crossAxisAlignment; @@ -299,10 +322,14 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin 0 || crossAxisAlignment == CrossAxisAlignment.baseline) { @@ -470,20 +492,23 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin= minMainSize); break; case FlexDirection.vertical: - size = constraints.constrain(new Size(crossSize, mainSize)); + size = constraints.constrain(new Size(crossSize, preferredSize)); crossSize = size.width; - assert(size.height == mainSize); + assert(isMainAxisSizeMax ? size.height == maxMainSize : size.height >= minMainSize); break; } } else { + assert(mainAxisSize == MainAxisSize.max); leadingSpace = 0.0; betweenSpace = 0.0; switch (_direction) { @@ -502,7 +527,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin children: _emptyWidgetList }) : super(key: key, children: children) { assert(direction != null); assert(mainAxisAlignment != null); + assert(mainAxisSize != null); assert(crossAxisAlignment != null); assert(crossAxisAlignment != CrossAxisAlignment.baseline || textBaseline != null); } @@ -1794,6 +1797,17 @@ class Flex extends MultiChildRenderObjectWidget { /// How the children should be placed along the main axis. 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. final CrossAxisAlignment crossAxisAlignment; @@ -1801,13 +1815,22 @@ class Flex extends MultiChildRenderObjectWidget { final TextBaseline textBaseline; @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 void updateRenderObject(BuildContext context, RenderFlex renderObject) { renderObject ..direction = direction ..mainAxisAlignment = mainAxisAlignment + ..mainAxisSize = mainAxisSize ..crossAxisAlignment = crossAxisAlignment ..textBaseline = textBaseline; } @@ -1820,12 +1843,13 @@ class Flex extends MultiChildRenderObjectWidget { class Row extends Flex { /// Creates a horizontal array of children. /// - /// The [direction], [mainAxisAlignment], and [crossAxisAlignment] arguments - /// must not be null. If [crossAxisAlignment] is - /// [CrossAxisAlignment.baseline], then [textBaseline] must not be null. + /// The [direction], [mainAxisAlignment], [mainAxisSize], and + /// [crossAxisAlignment] arguments must not be null. If [crossAxisAlignment] + /// is [CrossAxisAlignment.baseline], then [textBaseline] must not be null. Row({ Key key, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, + MainAxisSize mainAxisSize: MainAxisSize.max, CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, TextBaseline textBaseline, List children: _emptyWidgetList @@ -1834,6 +1858,7 @@ class Row extends Flex { key: key, direction: FlexDirection.horizontal, mainAxisAlignment: mainAxisAlignment, + mainAxisSize: mainAxisSize, crossAxisAlignment: crossAxisAlignment, textBaseline: textBaseline ); @@ -1846,12 +1871,13 @@ class Row extends Flex { class Column extends Flex { /// Creates a vertical array of children. /// - /// The [direction], [mainAxisAlignment], and [crossAxisAlignment] arguments - /// must not be null. If [crossAxisAlignment] is - /// [CrossAxisAlignment.baseline], then [textBaseline] must not be null. + /// The [direction], [mainAxisAlignment], [mainAxisSize], and + /// [crossAxisAlignment] arguments must not be null. If [crossAxisAlignment] + /// is [CrossAxisAlignment.baseline], then [textBaseline] must not be null. Column({ Key key, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, + MainAxisSize mainAxisSize: MainAxisSize.max, CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, TextBaseline textBaseline, List children: _emptyWidgetList @@ -1860,6 +1886,7 @@ class Column extends Flex { key: key, direction: FlexDirection.vertical, mainAxisAlignment: mainAxisAlignment, + mainAxisSize: mainAxisSize, crossAxisAlignment: crossAxisAlignment, textBaseline: textBaseline ); diff --git a/packages/flutter/test/widget/column_test.dart b/packages/flutter/test/widget/column_test.dart new file mode 100644 index 00000000000..ae6cee2d3b4 --- /dev/null +++ b/packages/flutter/test/widget/column_test.dart @@ -0,0 +1,389 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + +void main() { + testWidgets('Column with one flexible child', (WidgetTester tester) async { + final Key columnKey = new Key('column'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Column should be as high as the test: 600. + // Default is MainAxisAlignment.start so children so the children's + // top edges should be at 0, 100, 500, child2's height should be 400. + await tester.pumpWidget(new Center( + child: new Column( + key: columnKey, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Flexible(child: new Container(key: child1Key, width: 100.0, height: 100.0)), + new Container(key: child2Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(columnKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(600.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(0.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(400.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(500.0)); + }); + + testWidgets('Column with default main axis parameters', (WidgetTester tester) async { + final Key columnKey = new Key('column'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Column should be as high as the test: 600. + // Default is MainAxisAlignment.start so children so the children's + // top edges should be at 0, 100, 200 + await tester.pumpWidget(new Center( + child: new Column( + key: columnKey, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + new Container(key: child2Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(columnKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(600.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(0.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(200.0)); + }); + + testWidgets('Column with MainAxisAlignment.center', (WidgetTester tester) async { + final Key columnKey = new Key('column'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + + // Default is MainAxisSize.max so the Column should be as high as the test: 600. + // The 100x100 children's top edges should be at 200, 300 + await tester.pumpWidget(new Center( + child: new Column( + key: columnKey, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(columnKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(600.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(200.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(300.0)); + }); + + testWidgets('Column with MainAxisAlignment.end', (WidgetTester tester) async { + final Key columnKey = new Key('column'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Column should be as high as the test: 600. + // The 100x100 children's top edges should be at 300, 400, 500. + await tester.pumpWidget(new Center( + child: new Column( + key: columnKey, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + new Container(key: child2Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(columnKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(600.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(300.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(400.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(500.0)); + }); + + testWidgets('Column with MainAxisAlignment.spaceBetween', (WidgetTester tester) async { + final Key columnKey = new Key('column'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Column should be as high as the test: 600. + // The 100x100 children's top edges should be at 0, 250, 500 + await tester.pumpWidget(new Center( + child: new Column( + key: columnKey, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + new Container(key: child2Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(columnKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(600.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(0.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(250.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(500.0)); + }); + + testWidgets('Column with MainAxisAlignment.spaceAround', (WidgetTester tester) async { + final Key columnKey = new Key('column'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + final Key child3Key = new Key('child3'); + + // Default is MainAxisSize.max so the Column should be as high as the test: 600. + // The 100x100 children's top edges should be at 25, 175, 325, 475 + await tester.pumpWidget(new Center( + child: new Column( + key: columnKey, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + new Container(key: child2Key, width: 100.0, height: 100.0), + new Container(key: child3Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(columnKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(600.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(25.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(175.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(325.0)); + + renderBox = tester.renderObject(find.byKey(child3Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(475.0)); + }); + + testWidgets('Column with MainAxisAlignment.spaceEvenly', (WidgetTester tester) async { + final Key columnKey = new Key('column'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Column should be as high as the test: 600. + // The 100x20 children's top edges should be at 135, 290, 445 + await tester.pumpWidget(new Center( + child: new Column( + key: columnKey, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + new Container(key: child0Key, width: 100.0, height: 20.0), + new Container(key: child1Key, width: 100.0, height: 20.0), + new Container(key: child2Key, width: 100.0, height: 20.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(columnKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(600.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(20.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(135.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(20.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(290.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(20.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dy, equals(445.0)); + }); + + testWidgets('Column and MainAxisSize.min', (WidgetTester tester) async { + final Key flexKey = new Key('flexKey'); + + // Default is MainAxisSize.max so the Column should be as high as the test: 600. + await tester.pumpWidget(new Center( + child: new Column( + key: flexKey, + children: [ + new Container(width: 100.0, height: 100.0), + new Container(width: 100.0, height: 150.0) + ] + ) + )); + RenderBox renderBox = tester.renderObject(find.byKey(flexKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(600.0)); + + // Column with MainAxisSize.min without flexible children shrink wraps. + await tester.pumpWidget(new Center( + child: new Column( + key: flexKey, + mainAxisSize: MainAxisSize.min, + children: [ + new Container(width: 100.0, height: 100.0), + new Container(width: 100.0, height: 150.0) + ] + ) + )); + renderBox = tester.renderObject(find.byKey(flexKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(250.0)); + }); + + testWidgets('Column MainAxisSize.min 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( + mainAxisSize: MainAxisSize.min, + children: [ + new Container( + key: childKey, + width: 100.0, + height: 100.0 + ) + ] + ) + ) + )); + + RenderBox renderBox = tester.renderObject(find.byKey(childKey)); + expect(renderBox.size.width, equals(0.0)); + expect(renderBox.size.height, equals(100.0)); + }); +} diff --git a/packages/flutter/test/widget/flex_test.dart b/packages/flutter/test/widget/flex_test.dart index 98ccd430974..388d192ad1b 100644 --- a/packages/flutter/test/widget/flex_test.dart +++ b/packages/flutter/test/widget/flex_test.dart @@ -47,116 +47,4 @@ void main() { await tester.tap(find.text('X')); 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: [ - 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: [ - 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: [ - 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: [ - 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: [ - 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: [ - 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)); - }); } diff --git a/packages/flutter/test/widget/rotated_box_test.dart b/packages/flutter/test/widget/rotated_box_test.dart index 4bd2bd140f1..c95ab3d5da7 100644 --- a/packages/flutter/test/widget/rotated_box_test.dart +++ b/packages/flutter/test/widget/rotated_box_test.dart @@ -16,7 +16,7 @@ void main() { key: rotatedBoxKey, quarterTurns: 1, child: new Row( - mainAxisAlignment: MainAxisAlignment.collapse, + mainAxisSize: MainAxisSize.min, children: [ new GestureDetector( onTap: () { log.add('left'); }, diff --git a/packages/flutter/test/widget/row_test.dart b/packages/flutter/test/widget/row_test.dart new file mode 100644 index 00000000000..8ef3dab9008 --- /dev/null +++ b/packages/flutter/test/widget/row_test.dart @@ -0,0 +1,394 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + +void main() { + testWidgets('Row with one Flexible child', (WidgetTester tester) async { + final Key rowKey = new Key('row'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Row should be as wide as the test: 800. + // Default is MainAxisAlignment.start so children so the children's + // left edges should be at 0, 100, 700, child2's width should be 600 + await tester.pumpWidget(new Center( + child: new Row( + key: rowKey, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Flexible(child: new Container(key: child1Key, width: 100.0, height: 100.0)), + new Container(key: child2Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(rowKey)); + expect(renderBox.size.width, equals(800.0)); + expect(renderBox.size.height, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(0.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(600.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(700.0)); + }); + + testWidgets('Row with default main axis parameters', (WidgetTester tester) async { + final Key rowKey = new Key('row'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Row should be as wide as the test: 800. + // Default is MainAxisAlignment.start so children so the children's + // left edges should be at 0, 100, 200 + await tester.pumpWidget(new Center( + child: new Row( + key: rowKey, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + new Container(key: child2Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(rowKey)); + expect(renderBox.size.width, equals(800.0)); + expect(renderBox.size.height, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(0.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(200.0)); + }); + + testWidgets('Row with MainAxisAlignment.center', (WidgetTester tester) async { + final Key rowKey = new Key('row'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + + // Default is MainAxisSize.max so the Row should be as wide as the test: 800. + // The 100x100 children's left edges should be at 300, 400 + await tester.pumpWidget(new Center( + child: new Row( + key: rowKey, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(rowKey)); + expect(renderBox.size.width, equals(800.0)); + expect(renderBox.size.height, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(300.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(400.0)); + }); + + testWidgets('Row with MainAxisAlignment.end', (WidgetTester tester) async { + final Key rowKey = new Key('row'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Row should be as wide as the test: 800. + // The 100x100 children's left edges should be at 500, 600, 700. + await tester.pumpWidget(new Center( + child: new Row( + key: rowKey, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + new Container(key: child2Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(rowKey)); + expect(renderBox.size.width, equals(800.0)); + expect(renderBox.size.height, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(500.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(600.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(700.0)); + }); + + testWidgets('Row with MainAxisAlignment.spaceBetween', (WidgetTester tester) async { + final Key rowKey = new Key('row'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Row should be as wide as the test: 800. + // The 100x100 children's left edges should be at 0, 350, 700 + await tester.pumpWidget(new Center( + child: new Row( + key: rowKey, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + new Container(key: child2Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(rowKey)); + expect(renderBox.size.width, equals(800.0)); + expect(renderBox.size.height, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(0.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(350.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(700.0)); + }); + + testWidgets('Row with MainAxisAlignment.spaceAround', (WidgetTester tester) async { + final Key rowKey = new Key('row'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + final Key child3Key = new Key('child3'); + + // Default is MainAxisSize.max so the Row should be as wide as the test: 800. + // The 100x100 children's left edges should be at 50, 250, 450, 650 + await tester.pumpWidget(new Center( + child: new Row( + key: rowKey, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 100.0, height: 100.0), + new Container(key: child2Key, width: 100.0, height: 100.0), + new Container(key: child3Key, width: 100.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(rowKey)); + expect(renderBox.size.width, equals(800.0)); + expect(renderBox.size.height, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(50.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(250.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(450.0)); + + renderBox = tester.renderObject(find.byKey(child3Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(650.0)); + }); + + testWidgets('Row with MainAxisAlignment.spaceEvenly', (WidgetTester tester) async { + final Key rowKey = new Key('row'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + final Key child2Key = new Key('child2'); + + // Default is MainAxisSize.max so the Row should be as wide as the test: 800. + // The 200x100 children's left edges should be at 50, 300, 550 + await tester.pumpWidget(new Center( + child: new Row( + key: rowKey, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + new Container(key: child0Key, width: 200.0, height: 100.0), + new Container(key: child1Key, width: 200.0, height: 100.0), + new Container(key: child2Key, width: 200.0, height: 100.0), + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(rowKey)); + expect(renderBox.size.width, equals(800.0)); + expect(renderBox.size.height, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(200.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(50.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(200.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(300.0)); + + renderBox = tester.renderObject(find.byKey(child2Key)); + expect(renderBox.size.width, equals(200.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(550.0)); + }); + + testWidgets('Row and MainAxisSize.min', (WidgetTester tester) async { + final Key rowKey = new Key('rowKey'); + final Key child0Key = new Key('child0'); + final Key child1Key = new Key('child1'); + + // Row with MainAxisSize.min without flexible children shrink wraps. + // Row's width should be 250, children should be at 0, 100. + await tester.pumpWidget(new Center( + child: new Row( + key: rowKey, + mainAxisSize: MainAxisSize.min, + children: [ + new Container(key: child0Key, width: 100.0, height: 100.0), + new Container(key: child1Key, width: 150.0, height: 100.0) + ] + ) + )); + + RenderBox renderBox; + BoxParentData boxParentData; + + renderBox = tester.renderObject(find.byKey(rowKey)); + expect(renderBox.size.width, equals(250.0)); + expect(renderBox.size.height, equals(100.0)); + + renderBox = tester.renderObject(find.byKey(child0Key)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(0.0)); + + renderBox = tester.renderObject(find.byKey(child1Key)); + expect(renderBox.size.width, equals(150.0)); + expect(renderBox.size.height, equals(100.0)); + boxParentData = renderBox.parentData; + expect(boxParentData.offset.dx, equals(100.0)); + }); + + testWidgets('Row MainAxisSize.min 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 Row( + children: [ + new Container( + key: childKey, + width: 100.0, + height: 100.0 + ) + ], + mainAxisSize: MainAxisSize.min + ) + ) + )); + + RenderBox renderBox = tester.renderObject(find.byKey(childKey)); + expect(renderBox.size.width, equals(100.0)); + expect(renderBox.size.height, equals(0.0)); + }); +}