Rename Flexible to Expanded and improve docs (#6978)

This patch replaces uses of Flexible with Expanded where we're using
FlexFit.tight. We still need to think of a better name for the
FlexFit.loose variant.

Also, improve the docs for Row, Column, Flex, and RenderFlex to be more
problem-oriented and to give a complete account of the layout algorithn.

Fixes #6960
Fixes #5169
This commit is contained in:
Adam Barth 2016-11-21 23:16:43 -08:00 committed by GitHub
parent a0c567f751
commit 8ca4caa440
48 changed files with 300 additions and 198 deletions

View File

@ -91,7 +91,7 @@ class ComplexLayoutState extends State<ComplexLayout> {
), ),
body: new Column( body: new Column(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new LazyBlock( child: new LazyBlock(
key: new Key('main-scroll'), key: new Key('main-scroll'),
delegate: new FancyItemDelegate() delegate: new FancyItemDelegate()
@ -339,7 +339,7 @@ class UserHeader extends StatelessWidget {
height: 32.0 height: 32.0
) )
), ),
new Flexible( new Expanded(
child: new Column( child: new Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
@ -474,7 +474,7 @@ class ItemGalleryBox extends StatelessWidget {
values: tabNames, values: tabNames,
child: new Column( child: new Column(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new TabBarView<String>( child: new TabBarView<String>(
children: tabNames.map((String tabName) { children: tabNames.map((String tabName) {
return new Container( return new Container(
@ -484,7 +484,7 @@ class ItemGalleryBox extends StatelessWidget {
child: new Card( child: new Card(
child: new Column( child: new Column(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new Container( child: new Container(
decoration: new BoxDecoration( decoration: new BoxDecoration(
backgroundColor: Theme.of(context).primaryColor backgroundColor: Theme.of(context).primaryColor
@ -504,7 +504,7 @@ class ItemGalleryBox extends StatelessWidget {
icon: new Icon(Icons.event), icon: new Icon(Icons.event),
onPressed: () { print('Pressed event'); } onPressed: () { print('Pressed event'); }
), ),
new Flexible( new Expanded(
child: new Padding( child: new Padding(
padding: new EdgeInsets.only(left: 8.0), padding: new EdgeInsets.only(left: 8.0),
child: new Text('This is item $tabName') child: new Text('This is item $tabName')
@ -598,7 +598,7 @@ class GalleryDrawer extends StatelessWidget {
selected: ComplexLayoutApp.of(context).lightTheme, selected: ComplexLayoutApp.of(context).lightTheme,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Light')), new Expanded(child: new Text('Light')),
new Radio<bool>( new Radio<bool>(
value: true, value: true,
groupValue: ComplexLayoutApp.of(context).lightTheme, groupValue: ComplexLayoutApp.of(context).lightTheme,
@ -613,7 +613,7 @@ class GalleryDrawer extends StatelessWidget {
selected: !ComplexLayoutApp.of(context).lightTheme, selected: !ComplexLayoutApp.of(context).lightTheme,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Dark')), new Expanded(child: new Text('Dark')),
new Radio<bool>( new Radio<bool>(
value: false, value: false,
groupValue: ComplexLayoutApp.of(context).lightTheme, groupValue: ComplexLayoutApp.of(context).lightTheme,
@ -629,7 +629,7 @@ class GalleryDrawer extends StatelessWidget {
onPressed: () { ComplexLayoutApp.of(context).toggleAnimationSpeed(); }, onPressed: () { ComplexLayoutApp.of(context).toggleAnimationSpeed(); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Animate Slowly')), new Expanded(child: new Text('Animate Slowly')),
new Checkbox( new Checkbox(
value: timeDilation != 1.0, value: timeDilation != 1.0,
onChanged: (bool value) { ComplexLayoutApp.of(context).toggleAnimationSpeed(); } onChanged: (bool value) { ComplexLayoutApp.of(context).toggleAnimationSpeed(); }

View File

@ -213,7 +213,7 @@ class CardCollectionState extends State<CardCollection> {
onPressed: enabled ? callback : null, onPressed: enabled ? callback : null,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text(label)), new Expanded(child: new Text(label)),
new Checkbox( new Checkbox(
value: value, value: value,
onChanged: enabled ? (_) { callback(); } : null onChanged: enabled ? (_) { callback(); } : null
@ -229,7 +229,7 @@ class CardCollectionState extends State<CardCollection> {
onPressed: enabled ? () { onChanged(itemValue); } : null, onPressed: enabled ? () { onChanged(itemValue); } : null,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text(label)), new Expanded(child: new Text(label)),
new Radio<Map<int, Color>>( new Radio<Map<int, Color>>(
value: itemValue, value: itemValue,
groupValue: currentValue, groupValue: currentValue,
@ -246,7 +246,7 @@ class CardCollectionState extends State<CardCollection> {
onPressed: enabled ? () { onChanged(itemValue); } : null, onPressed: enabled ? () { onChanged(itemValue); } : null,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text(label)), new Expanded(child: new Text(label)),
new Radio<DismissDirection>( new Radio<DismissDirection>(
value: itemValue, value: itemValue,
groupValue: currentValue, groupValue: currentValue,
@ -263,7 +263,7 @@ class CardCollectionState extends State<CardCollection> {
onPressed: enabled ? () { onChanged(itemValue); } : null, onPressed: enabled ? () { onChanged(itemValue); } : null,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text(label)), new Expanded(child: new Text(label)),
new Radio<TextAlign>( new Radio<TextAlign>(
value: itemValue, value: itemValue,
groupValue: currentValue, groupValue: currentValue,
@ -374,7 +374,7 @@ class CardCollectionState extends State<CardCollection> {
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
leftArrowIcon, leftArrowIcon,
new Flexible( new Expanded(
child: new Text(backgroundMessage, child: new Text(backgroundMessage,
style: backgroundTextStyle, style: backgroundTextStyle,
textAlign: TextAlign.center textAlign: TextAlign.center

View File

@ -242,8 +242,10 @@ class DragAndDropAppState extends State<DragAndDropApp> {
), ),
body: new Column( body: new Column(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new Row( child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[ children: <Widget>[
new ExampleDragSource( new ExampleDragSource(
color: Colors.yellow[300], color: Colors.yellow[300],
@ -264,28 +266,26 @@ class DragAndDropAppState extends State<DragAndDropApp> {
child: new Text('above') child: new Text('above')
), ),
], ],
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround
) )
), ),
new Flexible( new Expanded(
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new ExampleDragTarget()), new Expanded(child: new ExampleDragTarget()),
new Flexible(child: new ExampleDragTarget()), new Expanded(child: new ExampleDragTarget()),
new Flexible(child: new ExampleDragTarget()), new Expanded(child: new ExampleDragTarget()),
new Flexible(child: new ExampleDragTarget()), new Expanded(child: new ExampleDragTarget()),
] ]
) )
), ),
new Flexible( new Expanded(
child: new Row( child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[ children: <Widget>[
new MovableBall(1, position, moveBall), new MovableBall(1, position, moveBall),
new MovableBall(2, position, moveBall), new MovableBall(2, position, moveBall),
new MovableBall(3, position, moveBall), new MovableBall(3, position, moveBall),
], ],
mainAxisAlignment: MainAxisAlignment.spaceAround
) )
), ),
] ]

View File

@ -102,7 +102,7 @@ class PageableListAppState extends State<PageableListApp> {
onPressed: toggleItemsWrap, onPressed: toggleItemsWrap,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Scrolling wraps around')), new Expanded(child: new Text('Scrolling wraps around')),
// TODO(abarth): Actually make this checkbox change this value. // TODO(abarth): Actually make this checkbox change this value.
new Checkbox(value: itemsWrap, onChanged: null) new Checkbox(value: itemsWrap, onChanged: null)
] ]

View File

@ -122,12 +122,12 @@ class _CalculatorState extends State<Calculator> {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[ children: <Widget>[
// Give the key-pad 3/5 of the vertical space and the display 2/5. // Give the key-pad 3/5 of the vertical space and the display 2/5.
new Flexible( new Expanded(
flex: 2, flex: 2,
child: new CalcDisplay(content: _expression.toString()) child: new CalcDisplay(content: _expression.toString())
), ),
new Divider(height: 1.0), new Divider(height: 1.0),
new Flexible( new Expanded(
flex: 3, flex: 3,
child: new KeyPad(calcState: this) child: new KeyPad(calcState: this)
) )
@ -170,7 +170,7 @@ class KeyPad extends StatelessWidget {
child: new Material( child: new Material(
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
// We set flex equal to the number of columns so that the main keypad // We set flex equal to the number of columns so that the main keypad
// and the op keypad have sizes proportional to their number of // and the op keypad have sizes proportional to their number of
// columns. // columns.
@ -200,7 +200,7 @@ class KeyPad extends StatelessWidget {
] ]
) )
), ),
new Flexible( new Expanded(
child: new Material( child: new Material(
color: themeData.backgroundColor, color: themeData.backgroundColor,
child: new Column( child: new Column(
@ -228,7 +228,7 @@ class KeyRow extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new Flexible( return new Expanded(
child: new Row( child: new Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: this.keys children: this.keys
@ -246,7 +246,7 @@ class CalcKey extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final Orientation orientation = MediaQuery.of(context).orientation; final Orientation orientation = MediaQuery.of(context).orientation;
return new Flexible( return new Expanded(
child: new InkResponse( child: new InkResponse(
onTap: this.onTap, onTap: this.onTap,
child: new Center( child: new Center(

View File

@ -83,7 +83,7 @@ class TravelDestinationItem extends StatelessWidget {
) )
), ),
// description and share/expore buttons // description and share/expore buttons
new Flexible( new Expanded(
child: new Padding( child: new Padding(
padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0), padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0),
child: new DefaultTextStyle( child: new DefaultTextStyle(

View File

@ -28,7 +28,7 @@ class _ContactCategory extends StatelessWidget {
width: 72.0, width: 72.0,
child: new Icon(icon, color: themeData.primaryColor) child: new Icon(icon, color: themeData.primaryColor)
), ),
new Flexible(child: new Column(children: children)) new Expanded(child: new Column(children: children))
] ]
) )
) )
@ -53,7 +53,7 @@ class _ContactItem extends StatelessWidget {
columnChildren.add(new Text(lines.last, style: themeData.textTheme.caption)); columnChildren.add(new Text(lines.last, style: themeData.textTheme.caption));
List<Widget> rowChildren = <Widget>[ List<Widget> rowChildren = <Widget>[
new Flexible( new Expanded(
child: new Column( child: new Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: columnChildren children: columnChildren

View File

@ -86,7 +86,7 @@ class _DateTimePicker extends StatelessWidget {
return new Row( return new Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
flex: 4, flex: 4,
child: new _InputDropdown( child: new _InputDropdown(
labelText: labelText, labelText: labelText,
@ -96,7 +96,7 @@ class _DateTimePicker extends StatelessWidget {
), ),
), ),
new SizedBox(width: 12.0), new SizedBox(width: 12.0),
new Flexible( new Expanded(
flex: 3, flex: 3,
child: new _InputDropdown( child: new _InputDropdown(
valueText: selectedTime.toString(), valueText: selectedTime.toString(),

View File

@ -45,14 +45,14 @@ class DualHeaderWithHint extends StatelessWidget {
return new Row( return new Row(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
flex: 2, flex: 2,
child: new Container( child: new Container(
margin: const EdgeInsets.only(left: 24.0), margin: const EdgeInsets.only(left: 24.0),
child: new Text(name, style: textTheme.body1.copyWith(fontSize: 15.0)) child: new Text(name, style: textTheme.body1.copyWith(fontSize: 15.0))
) )
), ),
new Flexible( new Expanded(
flex: 3, flex: 3,
child: new Container( child: new Container(
margin: const EdgeInsets.only(left: 24.0), margin: const EdgeInsets.only(left: 24.0),

View File

@ -35,7 +35,7 @@ class DateTimeItem extends StatelessWidget {
style: theme.textTheme.subhead, style: theme.textTheme.subhead,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new Container( child: new Container(
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
decoration: new BoxDecoration( decoration: new BoxDecoration(

View File

@ -344,7 +344,7 @@ class GridListDemoState extends State<GridListDemo> {
), ),
body: new Column( body: new Column(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new ScrollableGrid( child: new ScrollableGrid(
scrollableKey: _scrollableKey, scrollableKey: _scrollableKey,
delegate: new FixedColumnCountGridDelegate( delegate: new FixedColumnCountGridDelegate(

View File

@ -83,9 +83,7 @@ class IconsDemoState extends State<IconsDemo> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
new Flexible( new Column(
flex: 0,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
new Text('Size', style: textStyle), new Text('Size', style: textStyle),
@ -94,9 +92,8 @@ class IconsDemoState extends State<IconsDemo> {
buildSizeLabel(36, textStyle), buildSizeLabel(36, textStyle),
buildSizeLabel(48, textStyle) buildSizeLabel(48, textStyle)
] ]
)
), ),
new Flexible( new Expanded(
child: new Column( child: new Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
@ -108,7 +105,7 @@ class IconsDemoState extends State<IconsDemo> {
] ]
) )
), ),
new Flexible( new Expanded(
child: new Column( child: new Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
@ -122,7 +119,7 @@ class IconsDemoState extends State<IconsDemo> {
) )
] ]
), ),
new Flexible( new Expanded(
child: new Center( child: new Center(
child: new IconTheme( child: new IconTheme(
data: new IconThemeData(opacity: 1.0), data: new IconThemeData(opacity: 1.0),

View File

@ -55,7 +55,7 @@ class PageSelectorDemo extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween mainAxisAlignment: MainAxisAlignment.spaceBetween
) )
), ),
new Flexible( new Expanded(
child: new TabBarView<IconData>( child: new TabBarView<IconData>(
children: icons.map((IconData icon) { children: icons.map((IconData icon) {
return new Container( return new Container(

View File

@ -253,7 +253,7 @@ class RecipeCard extends StatelessWidget {
tag: recipe.imagePath, tag: recipe.imagePath,
child: new Image.asset(recipe.imagePath, fit: ImageFit.contain) child: new Image.asset(recipe.imagePath, fit: ImageFit.contain)
), ),
new Flexible( new Expanded(
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Padding( new Padding(
@ -264,7 +264,7 @@ class RecipeCard extends StatelessWidget {
height: 48.0 height: 48.0
) )
), ),
new Flexible( new Expanded(
child: new Column( child: new Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,

View File

@ -81,7 +81,7 @@ class VendorItem extends StatelessWidget {
) )
), ),
new SizedBox(width: 8.0), new SizedBox(width: 8.0),
new Flexible( new Expanded(
child: new Text(vendor.name, style: ShrineTheme.of(context).vendorItemStyle) child: new Text(vendor.name, style: ShrineTheme.of(context).vendorItemStyle)
) )
] ]
@ -192,7 +192,7 @@ class FeatureItem extends StatelessWidget {
child: new FeaturePriceItem(product: product) child: new FeaturePriceItem(product: product)
) )
), ),
new Flexible( new Expanded(
child: new CustomMultiChildLayout( child: new CustomMultiChildLayout(
delegate: new FeatureLayout(), delegate: new FeatureLayout(),
children: <Widget>[ children: <Widget>[

View File

@ -56,7 +56,7 @@ class OrderItem extends StatelessWidget {
) )
) )
), ),
new Flexible( new Expanded(
child: new Text(product.name, style: theme.featureTitleStyle) child: new Text(product.name, style: theme.featureTitleStyle)
) )
] ]

View File

@ -110,7 +110,7 @@ class TextFieldDemoState extends State<TextFieldDemo> {
new Row( new Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new InputFormField( child: new InputFormField(
key: _passwordFieldKey, key: _passwordFieldKey,
hintText: 'How do you log in?', hintText: 'How do you log in?',
@ -120,7 +120,7 @@ class TextFieldDemoState extends State<TextFieldDemo> {
) )
), ),
new SizedBox(width: 16.0), new SizedBox(width: 16.0),
new Flexible( new Expanded(
child: new InputFormField( child: new InputFormField(
hintText: 'How do you log in?', hintText: 'How do you log in?',
labelText: 'Re-type Password', labelText: 'Re-type Password',

View File

@ -29,7 +29,7 @@ class TextStyleItem extends StatelessWidget {
width: 72.0, width: 72.0,
child: new Text(name, style: nameStyle) child: new Text(name, style: nameStyle)
), ),
new Flexible( new Expanded(
child: new Text(text, style: style.copyWith(height: 1.0)) child: new Text(text, style: style.copyWith(height: 1.0))
) )
] ]

View File

@ -91,7 +91,7 @@ class TabbedComponentDemoScaffold extends StatelessWidget {
style: Theme.of(context).textTheme.subhead style: Theme.of(context).textTheme.subhead
) )
), ),
new Flexible(child: demo.widget) new Expanded(child: demo.widget)
] ]
); );
}).toList() }).toList()

View File

@ -128,7 +128,7 @@ class GalleryDrawer extends StatelessWidget {
selected: useLightTheme, selected: useLightTheme,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Light')), new Expanded(child: new Text('Light')),
new Radio<bool>( new Radio<bool>(
value: true, value: true,
groupValue: useLightTheme, groupValue: useLightTheme,
@ -144,7 +144,7 @@ class GalleryDrawer extends StatelessWidget {
selected: useLightTheme, selected: useLightTheme,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Dark')), new Expanded(child: new Text('Dark')),
new Radio<bool>( new Radio<bool>(
value: false, value: false,
groupValue: useLightTheme, groupValue: useLightTheme,
@ -161,7 +161,7 @@ class GalleryDrawer extends StatelessWidget {
selected: Theme.of(context).platform == TargetPlatform.android, selected: Theme.of(context).platform == TargetPlatform.android,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Android')), new Expanded(child: new Text('Android')),
new Radio<TargetPlatform>( new Radio<TargetPlatform>(
value: TargetPlatform.android, value: TargetPlatform.android,
groupValue: Theme.of(context).platform, groupValue: Theme.of(context).platform,
@ -178,7 +178,7 @@ class GalleryDrawer extends StatelessWidget {
selected: Theme.of(context).platform == TargetPlatform.iOS, selected: Theme.of(context).platform == TargetPlatform.iOS,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('iOS')), new Expanded(child: new Text('iOS')),
new Radio<TargetPlatform>( new Radio<TargetPlatform>(
value: TargetPlatform.iOS, value: TargetPlatform.iOS,
groupValue: Theme.of(context).platform, groupValue: Theme.of(context).platform,
@ -194,7 +194,7 @@ class GalleryDrawer extends StatelessWidget {
onPressed: () { onTimeDilationChanged(timeDilation != 1.0 ? 1.0 : 20.0); }, onPressed: () { onTimeDilationChanged(timeDilation != 1.0 ? 1.0 : 20.0); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Animate Slowly')), new Expanded(child: new Text('Animate Slowly')),
new Checkbox( new Checkbox(
value: timeDilation != 1.0, value: timeDilation != 1.0,
onChanged: (bool value) { onTimeDilationChanged(value ? 20.0 : 1.0); } onChanged: (bool value) { onTimeDilationChanged(value ? 20.0 : 1.0); }
@ -275,7 +275,7 @@ class GalleryDrawer extends StatelessWidget {
selected: showPerformanceOverlay, selected: showPerformanceOverlay,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Performance Overlay')), new Expanded(child: new Text('Performance Overlay')),
new Checkbox( new Checkbox(
value: showPerformanceOverlay, value: showPerformanceOverlay,
onChanged: (bool value) { onShowPerformanceOverlayChanged(!showPerformanceOverlay); } onChanged: (bool value) { onShowPerformanceOverlayChanged(!showPerformanceOverlay); }
@ -292,7 +292,7 @@ class GalleryDrawer extends StatelessWidget {
selected: checkerboardRasterCacheImages, selected: checkerboardRasterCacheImages,
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Checkerboard Raster Cache Images')), new Expanded(child: new Text('Checkerboard Raster Cache Images')),
new Checkbox( new Checkbox(
value: checkerboardRasterCacheImages, value: checkerboardRasterCacheImages,
onChanged: (bool value) { onCheckerboardRasterCacheImagesChanged(!checkerboardRasterCacheImages); } onChanged: (bool value) { onCheckerboardRasterCacheImagesChanged(!checkerboardRasterCacheImages); }

View File

@ -28,7 +28,7 @@ void main() {
await tester.pump(); await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it has finished. await tester.pump(const Duration(seconds: 1)); // Wait until it has finished.
Finder display = find.widgetWithText(Flexible, '12'); Finder display = find.widgetWithText(Expanded, '12');
expect(display, findsOneWidget); expect(display, findsOneWidget);
}); });
} }

View File

@ -37,7 +37,7 @@ class AdaptedGridItem extends StatelessWidget {
return new Card( return new Card(
child: new Column( child: new Column(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new Container( child: new Container(
decoration: new BoxDecoration( decoration: new BoxDecoration(
backgroundColor: Colors.lightBlueAccent[100] backgroundColor: Colors.lightBlueAccent[100]
@ -48,7 +48,7 @@ class AdaptedGridItem extends StatelessWidget {
margin: const EdgeInsets.only(left: 8.0), margin: const EdgeInsets.only(left: 8.0),
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new Text(name) child: new Text(name)
), ),
new IconButton( new IconButton(

View File

@ -130,7 +130,7 @@ class SectorAppState extends State<SectorApp> {
mainAxisAlignment: MainAxisAlignment.spaceAround mainAxisAlignment: MainAxisAlignment.spaceAround
) )
), ),
new Flexible( new Expanded(
child: new Container( child: new Container(
margin: new EdgeInsets.all(8.0), margin: new EdgeInsets.all(8.0),
decoration: new BoxDecoration( decoration: new BoxDecoration(

View File

@ -23,7 +23,7 @@ class Rectangle extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new Flexible( return new Expanded(
child: new Container( child: new Container(
decoration: new BoxDecoration(backgroundColor: color) decoration: new BoxDecoration(backgroundColor: color)
) )

View File

@ -153,7 +153,7 @@ class StockHomeState extends State<StockHome> {
onPressed: () => _handleStockModeChange(StockMode.optimistic), onPressed: () => _handleStockModeChange(StockMode.optimistic),
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Optimistic')), new Expanded(child: new Text('Optimistic')),
new Radio<StockMode>(value: StockMode.optimistic, groupValue: config.configuration.stockMode, onChanged: _handleStockModeChange) new Radio<StockMode>(value: StockMode.optimistic, groupValue: config.configuration.stockMode, onChanged: _handleStockModeChange)
] ]
) )
@ -163,7 +163,7 @@ class StockHomeState extends State<StockHome> {
onPressed: () => _handleStockModeChange(StockMode.pessimistic), onPressed: () => _handleStockModeChange(StockMode.pessimistic),
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Pessimistic')), new Expanded(child: new Text('Pessimistic')),
new Radio<StockMode>(value: StockMode.pessimistic, groupValue: config.configuration.stockMode, onChanged: _handleStockModeChange) new Radio<StockMode>(value: StockMode.pessimistic, groupValue: config.configuration.stockMode, onChanged: _handleStockModeChange)
] ]
) )

View File

@ -54,22 +54,22 @@ class StockRow extends StatelessWidget {
child: new StockArrow(percentChange: stock.percentChange) child: new StockArrow(percentChange: stock.percentChange)
) )
), ),
new Flexible( new Expanded(
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
flex: 2, flex: 2,
child: new Text( child: new Text(
stock.symbol stock.symbol
) )
), ),
new Flexible( new Expanded(
child: new Text( child: new Text(
lastSale, lastSale,
textAlign: TextAlign.right textAlign: TextAlign.right
) )
), ),
new Flexible( new Expanded(
child: new Text( child: new Text(
changeInPrice, changeInPrice,
textAlign: TextAlign.right textAlign: TextAlign.right

View File

@ -108,7 +108,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () => _confirmOptimismChange(), onPressed: () => _confirmOptimismChange(),
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Everything is awesome')), new Expanded(child: new Text('Everything is awesome')),
new Checkbox( new Checkbox(
value: config.configuration.stockMode == StockMode.optimistic, value: config.configuration.stockMode == StockMode.optimistic,
onChanged: (bool value) => _confirmOptimismChange() onChanged: (bool value) => _confirmOptimismChange()
@ -121,7 +121,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () { _handleBackupChanged(!(config.configuration.backupMode == BackupMode.enabled)); }, onPressed: () { _handleBackupChanged(!(config.configuration.backupMode == BackupMode.enabled)); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Back up stock list to the cloud')), new Expanded(child: new Text('Back up stock list to the cloud')),
new Switch( new Switch(
value: config.configuration.backupMode == BackupMode.enabled, value: config.configuration.backupMode == BackupMode.enabled,
onChanged: _handleBackupChanged onChanged: _handleBackupChanged
@ -134,7 +134,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () { _handleShowPerformanceOverlayChanged(!config.configuration.showPerformanceOverlay); }, onPressed: () { _handleShowPerformanceOverlayChanged(!config.configuration.showPerformanceOverlay); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Show rendering performance overlay')), new Expanded(child: new Text('Show rendering performance overlay')),
new Switch( new Switch(
value: config.configuration.showPerformanceOverlay, value: config.configuration.showPerformanceOverlay,
onChanged: _handleShowPerformanceOverlayChanged onChanged: _handleShowPerformanceOverlayChanged
@ -147,7 +147,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () { _handleShowSemanticsDebuggerChanged(!config.configuration.showSemanticsDebugger); }, onPressed: () { _handleShowSemanticsDebuggerChanged(!config.configuration.showSemanticsDebugger); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Show semantics overlay')), new Expanded(child: new Text('Show semantics overlay')),
new Switch( new Switch(
value: config.configuration.showSemanticsDebugger, value: config.configuration.showSemanticsDebugger,
onChanged: _handleShowSemanticsDebuggerChanged onChanged: _handleShowSemanticsDebuggerChanged
@ -164,7 +164,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () { _handleShowGridChanged(!config.configuration.debugShowGrid); }, onPressed: () { _handleShowGridChanged(!config.configuration.debugShowGrid); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Show material grid (for debugging)')), new Expanded(child: new Text('Show material grid (for debugging)')),
new Switch( new Switch(
value: config.configuration.debugShowGrid, value: config.configuration.debugShowGrid,
onChanged: _handleShowGridChanged onChanged: _handleShowGridChanged
@ -177,7 +177,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () { _handleShowSizesChanged(!config.configuration.debugShowSizes); }, onPressed: () { _handleShowSizesChanged(!config.configuration.debugShowSizes); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Show construction lines (for debugging)')), new Expanded(child: new Text('Show construction lines (for debugging)')),
new Switch( new Switch(
value: config.configuration.debugShowSizes, value: config.configuration.debugShowSizes,
onChanged: _handleShowSizesChanged onChanged: _handleShowSizesChanged
@ -190,7 +190,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () { _handleShowBaselinesChanged(!config.configuration.debugShowBaselines); }, onPressed: () { _handleShowBaselinesChanged(!config.configuration.debugShowBaselines); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Show baselines (for debugging)')), new Expanded(child: new Text('Show baselines (for debugging)')),
new Switch( new Switch(
value: config.configuration.debugShowBaselines, value: config.configuration.debugShowBaselines,
onChanged: _handleShowBaselinesChanged onChanged: _handleShowBaselinesChanged
@ -203,7 +203,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () { _handleShowLayersChanged(!config.configuration.debugShowLayers); }, onPressed: () { _handleShowLayersChanged(!config.configuration.debugShowLayers); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Show layer boundaries (for debugging)')), new Expanded(child: new Text('Show layer boundaries (for debugging)')),
new Switch( new Switch(
value: config.configuration.debugShowLayers, value: config.configuration.debugShowLayers,
onChanged: _handleShowLayersChanged onChanged: _handleShowLayersChanged
@ -216,7 +216,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () { _handleShowPointersChanged(!config.configuration.debugShowPointers); }, onPressed: () { _handleShowPointersChanged(!config.configuration.debugShowPointers); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Show pointer hit-testing (for debugging)')), new Expanded(child: new Text('Show pointer hit-testing (for debugging)')),
new Switch( new Switch(
value: config.configuration.debugShowPointers, value: config.configuration.debugShowPointers,
onChanged: _handleShowPointersChanged onChanged: _handleShowPointersChanged
@ -229,7 +229,7 @@ class StockSettingsState extends State<StockSettings> {
onPressed: () { _handleShowRainbowChanged(!config.configuration.debugShowRainbow); }, onPressed: () { _handleShowRainbowChanged(!config.configuration.debugShowRainbow); },
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
new Flexible(child: new Text('Show repaint rainbow (for debugging)')), new Expanded(child: new Text('Show repaint rainbow (for debugging)')),
new Switch( new Switch(
value: config.configuration.debugShowRainbow, value: config.configuration.debugShowRainbow,
onChanged: _handleShowRainbowChanged onChanged: _handleShowRainbowChanged

View File

@ -21,12 +21,12 @@ void main() {
setState = setStateRef; setState = setStateRef;
return new Column( return new Column(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new Center( child: new Center(
child: new FlutterLogo(size: 100.0), child: new FlutterLogo(size: 100.0),
), ),
), ),
new Flexible( new Expanded(
child: new Builder( child: new Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
List<Widget> children = <Widget>[]; List<Widget> children = <Widget>[];
@ -43,7 +43,7 @@ void main() {
}, },
), ),
), ),
new Flexible( new Expanded(
child: new Block( child: new Block(
padding: new EdgeInsets.symmetric(horizontal: 24.0), padding: new EdgeInsets.symmetric(horizontal: 24.0),
children: <Widget>[ new Text(explanation, textAlign: TextAlign.center) ] children: <Widget>[ new Text(explanation, textAlign: TextAlign.center) ]

View File

@ -252,7 +252,7 @@ class AboutDialog extends StatelessWidget {
List<Widget> body = <Widget>[]; List<Widget> body = <Widget>[];
if (icon != null) if (icon != null)
body.add(new IconTheme(data: new IconThemeData(size: 48.0), child: icon)); body.add(new IconTheme(data: new IconThemeData(size: 48.0), child: icon));
body.add(new Flexible( body.add(new Expanded(
child: new Padding( child: new Padding(
padding: new EdgeInsets.symmetric(horizontal: 24.0), padding: new EdgeInsets.symmetric(horizontal: 24.0),
child: new BlockBody( child: new BlockBody(

View File

@ -311,7 +311,7 @@ class BottomNavigationBarState extends State<BottomNavigationBar> with TickerPro
); );
for (int i = 0; i < config.labels.length; i += 1) { for (int i = 0; i < config.labels.length; i += 1) {
children.add( children.add(
new Flexible( new Expanded(
child: new InkResponse( child: new InkResponse(
onTap: () { onTap: () {
if (config.onTap != null) if (config.onTap != null)
@ -376,7 +376,7 @@ class BottomNavigationBarState extends State<BottomNavigationBar> with TickerPro
_computeWeight(); _computeWeight();
for (int i = 0; i < config.labels.length; i += 1) { for (int i = 0; i < config.labels.length; i += 1) {
children.add( children.add(
new Flexible( new Expanded(
// Since Flexible only supports integers, we're using large // Since Flexible only supports integers, we're using large
// numbers in order to simulate floating point flex values. // numbers in order to simulate floating point flex values.
flex: (_flex(animations[i]) * 1000.0).round(), flex: (_flex(animations[i]) * 1000.0).round(),

View File

@ -450,7 +450,7 @@ class DataTable extends StatelessWidget {
final bool isLightTheme = Theme.of(context).brightness == Brightness.light; final bool isLightTheme = Theme.of(context).brightness == Brightness.light;
if (showEditIcon) { if (showEditIcon) {
final Widget icon = new Icon(Icons.edit, size: 18.0); final Widget icon = new Icon(Icons.edit, size: 18.0);
label = new Flexible(child: label); label = new Expanded(child: label);
label = new Row(children: numeric ? <Widget>[ icon, label ] : <Widget>[ label, icon ]); label = new Row(children: numeric ? <Widget>[ icon, label ] : <Widget>[ label, icon ]);
} }
label = new Container( label = new Container(

View File

@ -118,7 +118,7 @@ class DrawerItem extends StatelessWidget {
} }
if (child != null) { if (child != null) {
children.add( children.add(
new Flexible( new Expanded(
child: new Padding( child: new Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0), padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: new AnimatedDefaultTextStyle( child: new AnimatedDefaultTextStyle(

View File

@ -116,7 +116,7 @@ class ExpansionPanelList extends StatelessWidget {
Row header = new Row( Row header = new Row(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new AnimatedContainer( child: new AnimatedContainer(
duration: animationDuration, duration: animationDuration,
curve: Curves.fastOutSlowIn, curve: Curves.fastOutSlowIn,

View File

@ -81,7 +81,7 @@ class GridTileBar extends StatelessWidget {
); );
if (title != null && subtitle != null) { if (title != null && subtitle != null) {
children.add( children.add(
new Flexible( new Expanded(
child: new Column( child: new Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -104,7 +104,7 @@ class GridTileBar extends StatelessWidget {
); );
} else if (title != null || subtitle != null) { } else if (title != null || subtitle != null) {
children.add( children.add(
new Flexible( new Expanded(
child: new DefaultTextStyle( child: new DefaultTextStyle(
style: darkTheme.textTheme.subhead, style: darkTheme.textTheme.subhead,
softWrap: false, softWrap: false,

View File

@ -344,7 +344,7 @@ class _InputContainerState extends State<InputContainer> {
child: config.icon child: config.icon
) )
), ),
new Flexible(child: textField) new Expanded(child: textField)
] ]
); );
} }

View File

@ -190,7 +190,7 @@ class ListItem extends StatelessWidget {
] ]
); );
} }
children.add(new Flexible( children.add(new Expanded(
child: center child: center
)); ));

View File

@ -273,7 +273,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
final List<Widget> headerWidgets = <Widget>[]; final List<Widget> headerWidgets = <Widget>[];
double leftPadding = 24.0; double leftPadding = 24.0;
if (_selectedRowCount == 0) { if (_selectedRowCount == 0) {
headerWidgets.add(new Flexible(child: config.header)); headerWidgets.add(new Expanded(child: config.header));
if (config.header is ButtonBar) { if (config.header is ButtonBar) {
// We adjust the padding when a button bar is present, because the // We adjust the padding when a button bar is present, because the
// ButtonBar introduces 2 pixels of outside padding, plus 2 pixels // ButtonBar introduces 2 pixels of outside padding, plus 2 pixels
@ -285,9 +285,9 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
} }
} else if (_selectedRowCount == 1) { } else if (_selectedRowCount == 1) {
// TODO(ianh): Real l10n. // TODO(ianh): Real l10n.
headerWidgets.add(new Flexible(child: new Text('1 item selected'))); headerWidgets.add(new Expanded(child: new Text('1 item selected')));
} else { } else {
headerWidgets.add(new Flexible(child: new Text('$_selectedRowCount items selected'))); headerWidgets.add(new Expanded(child: new Text('$_selectedRowCount items selected')));
} }
if (config.actions != null) { if (config.actions != null) {
headerWidgets.addAll( headerWidgets.addAll(

View File

@ -163,7 +163,7 @@ class SnackBar extends StatelessWidget {
); );
List<Widget> children = <Widget>[ List<Widget> children = <Widget>[
const SizedBox(width: _kSnackBarPadding), const SizedBox(width: _kSnackBarPadding),
new Flexible( new Expanded(
child: new Container( child: new Container(
padding: const EdgeInsets.symmetric(vertical: _kSingleLineVerticalPadding), padding: const EdgeInsets.symmetric(vertical: _kSingleLineVerticalPadding),
child: new DefaultTextStyle( child: new DefaultTextStyle(

View File

@ -576,7 +576,7 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
if (!_isLast(i)) if (!_isLast(i))
children.add( children.add(
new Flexible( new Expanded(
child: new Container( child: new Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0), margin: const EdgeInsets.symmetric(horizontal: 8.0),
height: 1.0, height: 1.0,
@ -599,7 +599,7 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
) )
) )
), ),
new Flexible( new Expanded(
child: new ScrollableViewport( child: new ScrollableViewport(
child: new Container( child: new Container(
margin: const EdgeInsets.all(24.0), margin: const EdgeInsets.all(24.0),

View File

@ -717,7 +717,7 @@ class _TimePickerDialogState extends State<_TimePickerDialog> {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[ children: <Widget>[
header, header,
new Flexible(child: picker), new Expanded(child: picker),
actions, actions,
] ]
) )
@ -735,7 +735,7 @@ class _TimePickerDialogState extends State<_TimePickerDialog> {
fit: FlexFit.loose, fit: FlexFit.loose,
child: new Column( child: new Column(
children: <Widget>[ children: <Widget>[
new Flexible(child: picker), new Expanded(child: picker),
actions, actions,
] ]
) )

View File

@ -77,7 +77,7 @@ class _UserAccountsDrawerHeaderState extends State<UserAccountsDrawerHeader> {
decoration: config.decoration, decoration: config.decoration,
child: new Column( child: new Column(
children: <Widget>[ children: <Widget>[
new Flexible( new Expanded(
child: new Stack( child: new Stack(
children: <Widget>[ children: <Widget>[
new Positioned( new Positioned(
@ -137,7 +137,7 @@ class _UserAccountsDrawerHeaderState extends State<UserAccountsDrawerHeader> {
style: const TextStyle(color: Colors.white), style: const TextStyle(color: Colors.white),
child: config.accountEmail child: config.accountEmail
), ),
new Flexible( new Expanded(
child: new Align( child: new Align(
alignment: FractionalOffset.centerRight, alignment: FractionalOffset.centerRight,
child: new Icon( child: new Icon(

View File

@ -107,22 +107,42 @@ enum CrossAxisAlignment {
typedef double _ChildSizingFunction(RenderBox child, double extent); typedef double _ChildSizingFunction(RenderBox child, double extent);
/// Implements the flex layout algorithm /// Displays its children in a one-dimensional array.
/// ///
/// In flex layout, children are arranged linearly along the main axis (either /// Layout for a [RenderFlex] proceeds in six steps:
/// horizontally or vertically). First, inflexible children (those with a null
/// flex factor) are allocated space along the main axis. If the flex is given
/// unlimited space in the main axis, the flex sizes its main axis to the total
/// size of the inflexible children along the main axis and forbids flexible
/// children. Otherwise, the flex expands to the maximum max-axis size and the
/// remaining space along is divided among the flexible children according to
/// their flex factors. Any remaining free space (i.e., if there aren't any
/// flexible children or some of the flexible children have a loose fit) is
/// allocated according to the [mainAxisAlignment] property.
/// ///
/// In the cross axis, children determine their own size. The flex then sizes /// 1. Layout each child a null or zero flex factor with unbounded main axis
/// its cross axis to fix the largest of its children. The children are then /// constraints and the incoming cross axis constraints. If the
/// positioned along the cross axis according to the [crossAxisAlignment] property. /// [crossAxisAlignment] is [CrossAxisAlignment.stretch], instead use tight
/// cross axis constraints that match the incoming max extent in the cross
/// axis.
/// 2. Divide the remaining main axis space among the children with non-zero
/// flex factors according to their flex factor. For example, a child with a
/// flex factor of 2.0 will receive twice the amount of main axis space as a
/// child with a flex factor of 1.0.
/// 3. Layout each of the remaining children with the same cross axis
/// constraints as in step 1, but instead of using unbounded main axis
/// constraints, use max axis constraints based on the amount of space
/// allocated in step 2. Children with [Flexible.fit] properties that are
/// [FlexFit.tight] are given tight constraints (i.e., forced to fill the
/// allocated space), and children with [Flexible.fit] properties that are
/// [FlexFit.loose] are given loose constraints (i.e., not forced to fill the
/// allocated space).
/// 4. The cross axis extent of the [RenderFlex] is the maximum cross axis
/// extent of the children (which will always satisfy the incoming
/// constraints).
/// 5. The main axis extent of the [RenderFlex] is determined by the
/// [mainAxisSize] property. If the [mainAxisSize] property is
/// [MainAxisSize.max], then the main axis extent of the [RenderFlex] is the
/// max extent of the incoming main axis constraints. If the [mainAxisSize]
/// property is [MainAxisSize.min], then the main axis extent of the [Flex]
/// is the sum of the main axis extents of the children (subject to the
/// incoming constraints).
/// 6. Determine the position for each child according to the
/// [mainAxisAlignment] and the [crossAxisAlignment]. For example, if the
/// [mainAxisAlignment] is [MainAxisAlignment.spaceBetween], any main axis
/// space that has not been allocated to children is divided evenly and
/// placed between the children.
class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, FlexParentData>, class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, FlexParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, FlexParentData> { RenderBoxContainerDefaultsMixin<RenderBox, FlexParentData> {
/// Creates a flex render object. /// Creates a flex render object.

View File

@ -1932,32 +1932,16 @@ class GridPlacementData<DataType> extends ParentDataWidget<GridRenderObjectWidge
} }
} }
/// A widget that uses the flex layout algorithm for its children. /// A widget that displays its children in a one-dimensional array.
/// ///
/// The [Flex] widget allows you to control the axis along which the children are /// The [Flex] widget allows you to control the axis along which the children are
/// placed (horizontal or vertical). This is referred to as the _main axis_. If /// placed (horizontal or vertical). This is referred to as the _main axis_. If
/// you know the main axis in advance, then consider using a [Row] (if it's /// you know the main axis in advance, then consider using a [Row] (if it's
/// horizontal) or [Column] (if it's vertical) instead, since that will be less /// horizontal) or [Column] (if it's vertical) instead, because that will be less
/// verbose. /// verbose.
/// ///
/// Each child of a [Flex] widget is either flexible or inflexible. The [Flex] /// To cause a child to expand to fill the available vertical space, wrap the
/// first lays out its inflexible children and subtracts their total length /// child in an [Expanded] widget.
/// along the main axis to determine how much free space is available. The
/// [Flex] then divides this free space among the flexible children in a ratio
/// determined by their [Flexible.flex] properties. To control the flex of child
/// widgets, see the [Flexible] widget.
///
/// The [mainAxisAlignment] property determines how the remaining free space (if
/// any) in the main direction is allocated after the flexible children are
/// dealt with. The [crossAxisAlignment] property determines how children are
/// positioned in the cross direction.
///
/// By default, a [Flex] will size itself along the main axis to the maximum
/// size permitted by its parent, unless that would be infinite (e.g. if it is
/// in a [Block] with the same main axis), in which case it will shrink-wrap its
/// children. The [mainAxisSize] property can be used to control this.
///
/// For more details about the flex layout algorithm, see [RenderFlex].
/// ///
/// The [Flex] widget does not scroll (and in general it is considered an error /// The [Flex] widget does not scroll (and in general it is considered an error
/// to have more children in a [Flex] than will fit in the available room). If /// to have more children in a [Flex] than will fit in the available room). If
@ -1966,6 +1950,41 @@ class GridPlacementData<DataType> extends ParentDataWidget<GridRenderObjectWidge
/// ///
/// If you only have one child, then rather than using [Flex], [Row], or /// If you only have one child, then rather than using [Flex], [Row], or
/// [Column], consider using [Align] or [Center] to position the child. /// [Column], consider using [Align] or [Center] to position the child.
///
/// ## Layout algorithm
///
/// Layout for a [Flex] proceeds in six steps:
///
/// 1. Layout each child a null or zero flex factor (e.g., those that are not
/// [Expanded]) with unbounded main axis constraints and the incoming
/// cross axis constraints. If the [crossAxisAlignment] is
/// [CrossAxisAlignment.stretch], instead use tight cross axis constraints
/// that match the incoming max extent in the cross axis.
/// 2. Divide the remaining main axis space among the children with non-zero
/// flex factors (e.g., those that are [Expanded]) according to their flex
/// factor. For example, a child with a flex factor of 2.0 will receive twice
/// the amount of main axis space as a child with a flex factor of 1.0.
/// 3. Layout each of the remaining children with the same cross axis
/// constraints as in step 1, but instead of using unbounded main axis
/// constraints, use max axis constraints based on the amount of space
/// allocated in step 2. Children with [Flexible.fit] properties that are
/// [FlexFit.tight] are given tight constraints (i.e., forced to fill the
/// allocated space), and children with [Flexible.fit] properties that are
/// [FlexFit.loose] are given loose constraints (i.e., not forced to fill the
/// allocated space).
/// 4. The cross axis extent of the [Flex] is the maximum cross axis extent of
/// the children (which will always satisfy the incoming constraints).
/// 5. The main axis extent of the [Flex] is determined by the [mainAxisSize]
/// property. If the [mainAxisSize] property is [MainAxisSize.max], then the
/// main axis extent of the [Flex] is the max extent of the incoming main
/// axis constraints. If the [mainAxisSize] property is [MainAxisSize.min],
/// then the main axis extent of the [Flex] is the sum of the main axis
/// extents of the children (subject to the incoming constraints).
/// 6. Determine the position for each child according to the
/// [mainAxisAlignment] and the [crossAxisAlignment]. For example, if the
/// [mainAxisAlignment] is [MainAxisAlignment.spaceBetween], any main axis
/// space that has not been allocated to children is divided evenly and
/// placed between the children.
class Flex extends MultiChildRenderObjectWidget { class Flex extends MultiChildRenderObjectWidget {
/// Creates a flex layout. /// Creates a flex layout.
/// ///
@ -1999,6 +2018,10 @@ class Flex extends MultiChildRenderObjectWidget {
final Axis direction; final Axis direction;
/// How the children should be placed along the main axis. /// How the children should be placed along the main axis.
///
/// For example, [MainAxisAlignment.start], the default, places the children
/// at the start (i.e., the left for a [Row] or the top for a [Column]) of the
/// main axis.
final MainAxisAlignment mainAxisAlignment; final MainAxisAlignment mainAxisAlignment;
/// How much space space should be occupied in the main axis. /// How much space space should be occupied in the main axis.
@ -2014,6 +2037,9 @@ class Flex extends MultiChildRenderObjectWidget {
final MainAxisSize mainAxisSize; final MainAxisSize mainAxisSize;
/// How the children should be placed along the cross axis. /// How the children should be placed along the cross axis.
///
/// For example, [CrossAxisAlignment.center], the default, centers the
/// children in the cross axis (e.g., horizontally for a [Column]).
final CrossAxisAlignment crossAxisAlignment; final CrossAxisAlignment crossAxisAlignment;
/// If aligning items according to their baseline, which baseline to use. /// If aligning items according to their baseline, which baseline to use.
@ -2041,26 +2067,10 @@ class Flex extends MultiChildRenderObjectWidget {
} }
} }
/// A widget that lays out its children in a horizontal array. /// A widget that displays its children in a horizontal array.
/// ///
/// Each child of a [Row] widget is either flexible or inflexible. The [Row] /// To cause a child to expand to fill the available horizontal space, wrap the
/// first lays out its inflexible children and subtracts their total width to /// child in an [Expanded] widget.
/// determine how much free space is available. The [Row] then divides this free
/// space among the flexible children in a ratio determined by their
/// [Flexible.flex] properties. To control the flex of child widgets, see the
/// [Flexible] widget.
///
/// The [mainAxisAlignment] property determines how the remaining horizontal
/// free space (if any) is allocated after the flexible children are dealt with.
/// The [crossAxisAlignment] property determines how children are positioned
/// vertically.
///
/// By default, a [Row] will size itself vertically to the maximum size
/// permitted by its parent, unless that would be infinitely wide (e.g. if it is
/// in a horizontal [Block]), in which case it will shrink-wrap its children.
/// The [mainAxisSize] property can be used to control this.
///
/// For more details about the flex layout algorithm, see [RenderFlex].
/// ///
/// The [Row] widget does not scroll (and in general it is considered an error /// The [Row] widget does not scroll (and in general it is considered an error
/// to have more children in a [Row] than will fit in the available room). If /// to have more children in a [Row] than will fit in the available room). If
@ -2071,6 +2081,39 @@ class Flex extends MultiChildRenderObjectWidget {
/// ///
/// If you only have one child, then consider using [Align] or [Center] to /// If you only have one child, then consider using [Align] or [Center] to
/// position the child. /// position the child.
///
/// ## Layout algorithm
///
/// Layout for a [Row] proceeds in six steps:
///
/// 1. Layout each child a null or zero flex factor (e.g., those that are not
/// [Expanded]) with unbounded horizontal constraints and the incoming
/// vertical constraints. If the [crossAxisAlignment] is
/// [CrossAxisAlignment.stretch], instead use tight vertical constraints that
/// match the incoming max height.
/// 2. Divide the remaining horizontal space among the children with non-zero
/// flex factors (e.g., those that are [Expanded]) according to their flex
/// factor. For example, a child with a flex factor of 2.0 will receive twice
/// the amount of horizontal space as a child with a flex factor of 1.0.
/// 3. Layout each of the remaining children with the same vertical constraints
/// as in step 1, but instead of using unbounded horizontal constraints, use
/// horizontal constraints based on the amount of space allocated in step 2.
/// Children with [Flexible.fit] properties that are [FlexFit.tight] are
/// given tight constraints (i.e., forced to fill the allocated space), and
/// children with [Flexible.fit] properties that are [FlexFit.loose] are
/// given loose constraints (i.e., not forced to fill the allocated space).
/// 4. The height of the [Row] is the maximum height of the children (which will
/// always satisfy the incoming vertical constraints).
/// 5. The width of the [Row] is determined by the [mainAxisSize] property. If
/// the [mainAxisSize] property is [MainAxisSize.max], then the width of the
/// [Row] is the max width of the incoming constraints. If the [mainAxisSize]
/// property is [MainAxisSize.min], then the width of the [Row] is the sum
/// of widths of the children (subject to the incoming constraints).
/// 6. Determine the position for each child according to the
/// [mainAxisAlignment] and the [crossAxisAlignment]. For example, if the
/// [mainAxisAlignment] is [MainAxisAlignment.spaceBetween], any horizontal
/// space that has not been allocated to children is divided evenly and
/// placed between the children.
class Row extends Flex { class Row extends Flex {
/// Creates a horizontal array of children. /// Creates a horizontal array of children.
/// ///
@ -2095,36 +2138,55 @@ class Row extends Flex {
); );
} }
/// A widget that lays out its children in a vertical array. /// A widget that displays its children in a vertical array.
/// ///
/// Each child of a [Column] widget is either flexible or inflexible. The /// To cause a child to expand to fill the available vertical space, wrap the
/// [Column] first lays out its inflexible children and subtracts their total /// child in an [Expanded] widget.
/// height to determine how much free space is available. The [Column] then
/// divides this free space among the flexible children in a ratio determined by
/// their [Flexible.flex] properties. To control the flex of child widgets, see
/// the [Flexible] widget.
/// ///
/// The [mainAxisAlignment] property determines how the remaining vertical free /// The [Column] widget does not scroll (and in general it is considered an error
/// space (if any) is allocated after the flexible children are dealt with. The /// to have more children in a [Column] than will fit in the available room). If
/// [crossAxisAlignment] property determines how children are positioned /// you have a line of widgets and want them to be able to scroll if there is
/// horizontally. /// insufficient room, consider using a [Block].
///
/// By default, a [Column] will size itself vertically to the maximum size
/// permitted by its parent, unless that would be infinitely high (e.g. if it is
/// in a vertical [Block]), in which case it will shrink-wrap its children. The
/// [mainAxisSize] property can be used to control this.
///
/// For more details about the flex layout algorithm, see [RenderFlex].
///
/// The [Column] widget does not scroll (and in general it is considered an
/// error to have more children in a [Column] than will fit in the available
/// room). If you have a list of widgets and want them to be able to scroll if
/// there is insufficient room, consider using a [Block].
/// ///
/// For a horizontal variant, see [Row]. /// For a horizontal variant, see [Row].
/// ///
/// If you only have one child, then consider using [Align] or [Center] to /// If you only have one child, then consider using [Align] or [Center] to
/// position the child. /// position the child.
///
/// ## Layout algorithm
///
/// Layout for a [Column] proceeds in six steps:
///
/// 1. Layout each child a null or zero flex factor (e.g., those that are not
/// [Expanded]) with unbounded vertical constraints and the incoming
/// horizontal constraints. If the [crossAxisAlignment] is
/// [CrossAxisAlignment.stretch], instead use tight horizontal constraints
/// that match the incoming max width.
/// 2. Divide the remaining vertical space among the children with non-zero
/// flex factors (e.g., those that are [Expanded]) according to their flex
/// factor. For example, a child with a flex factor of 2.0 will receive twice
/// the amount of vertical space as a child with a flex factor of 1.0.
/// 3. Layout each of the remaining children with the same horizontal
/// constraints as in step 1, but instead of using unbounded vertical
/// constraints, use vertical constraints based on the amount of space
/// allocated in step 2. Children with [Flexible.fit] properties that are
/// [FlexFit.tight] are given tight constraints (i.e., forced to fill the
/// allocated space), and children with [Flexible.fit] properties that are
/// [FlexFit.loose] are given loose constraints (i.e., not forced to fill the
/// allocated space).
/// 4. The width of the [Column] is the maximum width of the children (which
/// will always satisfy the incoming horizontal constraints).
/// 5. The height of the [Column] is determined by the [mainAxisSize] property.
/// If the [mainAxisSize] property is [MainAxisSize.max], then the height of
/// the [Column] is the max height of the incoming constraints. If the
/// [mainAxisSize] property is [MainAxisSize.min], then the height of the
/// [Column] is the sum of heights of the children (subject to the incoming
/// constraints).
/// 6. Determine the position for each child according to the
/// [mainAxisAlignment] and the [crossAxisAlignment]. For example, if the
/// [mainAxisAlignment] is [MainAxisAlignment.spaceBetween], any vertical
/// space that has not been allocated to children is divided evenly and
/// placed between the children.
class Column extends Flex { class Column extends Flex {
/// Creates a vertical array of children. /// Creates a vertical array of children.
/// ///
@ -2162,7 +2224,7 @@ class Flexible extends ParentDataWidget<Flex> {
Key key, Key key,
this.flex: 1, this.flex: 1,
this.fit: FlexFit.tight, this.fit: FlexFit.tight,
@required Widget child @required Widget child,
}) : super(key: key, child: child); }) : super(key: key, child: child);
/// The flex factor to use for this child /// The flex factor to use for this child
@ -2212,6 +2274,29 @@ class Flexible extends ParentDataWidget<Flex> {
} }
} }
/// A widget that expands a child of a [Row], [Column], or [Flex].
///
/// Using an [Expanded] widget to make a child of a [Row], [Column], or [Flex]
/// expand to fill the available space in the main axis (e.g., horizontally for
/// a [Row] or vertically for a [Column]). If multiple children are expanded,
/// the available space is divided amoung them according to the [flex] factor.
///
/// An [Expanded] widget must be a descendant of a [Row], [Column], or [Flex],
/// and the path from the [Flexible] widget to its enclosing [Row], [Column], or
/// [Flex] must contain only [StatelessWidget]s or [StatefulWidget]s (not other
/// kinds of widgets, like [RenderObjectWidget]s).
class Expanded extends Flexible {
/// Creates a widget that expands a child of a [Row], [Column], or [Flex]
/// expand to fill the available space in the main axis.
Expanded({
Key key,
int flex: 1,
@required Widget child,
}) : super(key: key, flex: flex, fit: FlexFit.tight, child: child) {
assert(flex > 0);
}
}
/// A widget that implements the flow layout algorithm. /// A widget that implements the flow layout algorithm.
/// ///
/// Flow layouts are optimized for repositioning children using transformation /// Flow layouts are optimized for repositioning children using transformation

View File

@ -22,7 +22,7 @@ Widget buildFrame(ScrollableEdge clampedEdge) {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
new SizedBox(height: 100.0, child: new Text('top')), new SizedBox(height: 100.0, child: new Text('top')),
new Flexible(child: new Container()), new Expanded(child: new Container()),
new SizedBox(height: 100.0, child: new Text('bottom')), new SizedBox(height: 100.0, child: new Text('bottom')),
] ]
) )

View File

@ -21,7 +21,7 @@ void main() {
key: columnKey, key: columnKey,
children: <Widget>[ children: <Widget>[
new Container(key: child0Key, width: 100.0, height: 100.0), new Container(key: child0Key, width: 100.0, height: 100.0),
new Flexible(child: new Container(key: child1Key, width: 100.0, height: 100.0)), new Expanded(child: new Container(key: child1Key, width: 100.0, height: 100.0)),
new Container(key: child2Key, width: 100.0, height: 100.0), new Container(key: child2Key, width: 100.0, height: 100.0),
] ]
) )

View File

@ -56,10 +56,10 @@ class Wrapper extends StatelessWidget {
void main() { void main() {
testWidgets('Applying parent data inside a LayoutBuilder', (WidgetTester tester) async { testWidgets('Applying parent data inside a LayoutBuilder', (WidgetTester tester) async {
int frame = 0; int frame = 1;
await tester.pumpWidget(new SizeChanger( // when this is triggered, the child LayoutBuilder will build again await tester.pumpWidget(new SizeChanger( // when this is triggered, the child LayoutBuilder will build again
child: new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { child: new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
return new Column(children: <Widget>[new Flexible( return new Column(children: <Widget>[new Expanded(
flex: frame, // this is different after the next pump, so that the parentData has to be applied again flex: frame, // this is different after the next pump, so that the parentData has to be applied again
child: new Container(height: 100.0), child: new Container(height: 100.0),
)]); )]);

View File

@ -21,7 +21,7 @@ void main() {
key: rowKey, key: rowKey,
children: <Widget>[ children: <Widget>[
new Container(key: child0Key, width: 100.0, height: 100.0), new Container(key: child0Key, width: 100.0, height: 100.0),
new Flexible(child: new Container(key: child1Key, width: 100.0, height: 100.0)), new Expanded(child: new Container(key: child1Key, width: 100.0, height: 100.0)),
new Container(key: child2Key, width: 100.0, height: 100.0), new Container(key: child2Key, width: 100.0, height: 100.0),
] ]
) )

View File

@ -410,7 +410,7 @@ class _Block {
width: listIndents.length * markdownStyle.listIndent, width: listIndents.length * markdownStyle.listIndent,
child: bullet child: bullet
), ),
new Flexible(child: contents) new Expanded(child: contents)
] ]
); );
} }