Commit 79364f0a authored by Adam Barth's avatar Adam Barth Committed by GitHub

Add Container.align and Container.position (#5128)

These let you add Align widget to the inside or outside of a container.
Several customers have asked for these properties.

Fixes #4950
parent 534097ff
...@@ -284,10 +284,8 @@ class CardCollectionState extends State<CardCollection> { ...@@ -284,10 +284,8 @@ class CardCollectionState extends State<CardCollection> {
flexibleSpace: new Container( flexibleSpace: new Container(
padding: const EdgeInsets.only(left: 72.0), padding: const EdgeInsets.only(left: 72.0),
height: 128.0, height: 128.0,
child: new Align( align: const FractionalOffset(0.0, 0.75),
alignment: const FractionalOffset(0.0, 0.75), child: new Text('Swipe Away: ${_cardModels.length}', style: Theme.of(context).primaryTextTheme.title)
child: new Text('Swipe Away: ${_cardModels.length}', style: Theme.of(context).primaryTextTheme.title)
)
) )
); );
} }
......
...@@ -166,20 +166,16 @@ class FullScreenDialogDemoState extends State<FullScreenDialogDemo> { ...@@ -166,20 +166,16 @@ class FullScreenDialogDemoState extends State<FullScreenDialogDemo> {
decoration: new BoxDecoration( decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(color: theme.dividerColor)) border: new Border(bottom: new BorderSide(color: theme.dividerColor))
), ),
child: new Align( align: FractionalOffset.bottomLeft,
alignment: FractionalOffset.bottomLeft, child: new Text('Event name', style: theme.textTheme.display2)
child: new Text('Event name', style: theme.textTheme.display2)
)
), ),
new Container( new Container(
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
decoration: new BoxDecoration( decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(color: theme.dividerColor)) border: new Border(bottom: new BorderSide(color: theme.dividerColor))
), ),
child: new Align( align: FractionalOffset.bottomLeft,
alignment: FractionalOffset.bottomLeft, child: new Text('Location', style: theme.textTheme.title.copyWith(color: Colors.black54))
child: new Text('Location', style: theme.textTheme.title.copyWith(color: Colors.black54))
)
), ),
new Column( new Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
......
...@@ -331,7 +331,7 @@ class _RecipePageState extends State<_RecipePage> { ...@@ -331,7 +331,7 @@ class _RecipePageState extends State<_RecipePage> {
const double fabHalfSize = 28.0; // TODO(mpcomplete): needs to adapt to screen size const double fabHalfSize = 28.0; // TODO(mpcomplete): needs to adapt to screen size
return new Hero( return new Hero(
tag: config.recipe.imagePath, tag: config.recipe.imagePath,
child: new DecoratedBox( child: new Container(
decoration: new BoxDecoration( decoration: new BoxDecoration(
backgroundColor: Theme.of(context).canvasColor, backgroundColor: Theme.of(context).canvasColor,
backgroundImage: new BackgroundImage( backgroundImage: new BackgroundImage(
...@@ -340,33 +340,31 @@ class _RecipePageState extends State<_RecipePage> { ...@@ -340,33 +340,31 @@ class _RecipePageState extends State<_RecipePage> {
fit: fullWidth ? ImageFit.fitWidth : ImageFit.cover fit: fullWidth ? ImageFit.fitWidth : ImageFit.cover
) )
), ),
child: new Align( align: FractionalOffset.bottomCenter,
alignment: FractionalOffset.bottomCenter, child: new Block(
child: new Block( children: <Widget>[
children: <Widget>[ new Padding(
new Padding( padding: new EdgeInsets.only(top: _getAppBarHeight(context)),
padding: new EdgeInsets.only(top: _getAppBarHeight(context)), child: new Stack(
child: new Stack( children: <Widget>[
children: <Widget>[ new Padding(
new Padding( padding: new EdgeInsets.only(top: fabHalfSize),
padding: new EdgeInsets.only(top: fabHalfSize), child: new SizedBox(
child: new SizedBox( width: fullWidth ? null : _kRecipePageMaxWidth,
width: fullWidth ? null : _kRecipePageMaxWidth, child: new _RecipeSheet(recipe: config.recipe)
child: new _RecipeSheet(recipe: config.recipe)
)
),
new Positioned(
right: 16.0,
child: new FloatingActionButton(
child: new Icon(isFavorite ? Icons.favorite : Icons.favorite_border),
onPressed: _toggleFavorite
)
) )
] ),
) new Positioned(
right: 16.0,
child: new FloatingActionButton(
child: new Icon(isFavorite ? Icons.favorite : Icons.favorite_border),
onPressed: _toggleFavorite
)
)
]
) )
] )
) ]
) )
) )
); );
......
...@@ -71,10 +71,8 @@ class GalleryHomeState extends State<GalleryHome> { ...@@ -71,10 +71,8 @@ class GalleryHomeState extends State<GalleryHome> {
new Container( new Container(
height: 48.0, height: 48.0,
padding: const EdgeInsets.only(left: 16.0), padding: const EdgeInsets.only(left: 16.0),
child: new Align( align: FractionalOffset.centerLeft,
alignment: FractionalOffset.centerLeft, child: new Text(galleryItem.category, style: headerStyle)
child: new Text(galleryItem.category, style: headerStyle)
)
) )
); );
category = galleryItem.category; category = galleryItem.category;
......
...@@ -406,21 +406,19 @@ class DataTable extends StatelessWidget { ...@@ -406,21 +406,19 @@ class DataTable extends StatelessWidget {
label = new Container( label = new Container(
padding: padding, padding: padding,
height: _kHeadingRowHeight, height: _kHeadingRowHeight,
child: new Align( align: new FractionalOffset(numeric ? 1.0 : 0.0, 0.5), // TODO(ianh): RTL for non-numeric
alignment: new FractionalOffset(numeric ? 1.0 : 0.0, 0.5), // TODO(ianh): RTL for non-numeric child: new AnimatedDefaultTextStyle(
child: new AnimatedDefaultTextStyle( style: new TextStyle(
style: new TextStyle( // TODO(ianh): font family should be Roboto; see https://github.com/flutter/flutter/issues/3116
// TODO(ianh): font family should be Roboto; see https://github.com/flutter/flutter/issues/3116 fontWeight: FontWeight.w500,
fontWeight: FontWeight.w500, fontSize: _kHeadingFontSize,
fontSize: _kHeadingFontSize, height: _kHeadingRowHeight / _kHeadingFontSize,
height: _kHeadingRowHeight / _kHeadingFontSize, color: (Theme.of(context).brightness == Brightness.light)
color: (Theme.of(context).brightness == Brightness.light) ? ((onSort != null && sorted) ? Colors.black87 : Colors.black54)
? ((onSort != null && sorted) ? Colors.black87 : Colors.black54) : ((onSort != null && sorted) ? Colors.white : Colors.white70)
: ((onSort != null && sorted) ? Colors.white : Colors.white70) ),
), duration: _kSortArrowAnimationDuration,
duration: _kSortArrowAnimationDuration, child: label
child: label
)
) )
); );
if (tooltip != null) { if (tooltip != null) {
...@@ -458,23 +456,21 @@ class DataTable extends StatelessWidget { ...@@ -458,23 +456,21 @@ class DataTable extends StatelessWidget {
label = new Container( label = new Container(
padding: padding, padding: padding,
height: _kDataRowHeight, height: _kDataRowHeight,
child: new Align( align: new FractionalOffset(numeric ? 1.0 : 0.0, 0.5), // TODO(ianh): RTL for non-numeric
alignment: new FractionalOffset(numeric ? 1.0 : 0.0, 0.5), // TODO(ianh): RTL for non-numeric child: new DefaultTextStyle(
child: new DefaultTextStyle( style: new TextStyle(
style: new TextStyle( // TODO(ianh): font family should be Roboto; see https://github.com/flutter/flutter/issues/3116
// TODO(ianh): font family should be Roboto; see https://github.com/flutter/flutter/issues/3116 fontSize: 13.0,
fontSize: 13.0, color: isLightTheme
color: isLightTheme ? (placeholder ? Colors.black38 : Colors.black87)
? (placeholder ? Colors.black38 : Colors.black87) : (placeholder ? Colors.white30 : Colors.white70)
: (placeholder ? Colors.white30 : Colors.white70) ),
child: new IconTheme.merge(
context: context,
data: new IconThemeData(
color: isLightTheme ? Colors.black54 : Colors.white70
), ),
child: new IconTheme.merge( child: new DropDownButtonHideUnderline(child: label)
context: context,
data: new IconThemeData(
color: isLightTheme ? Colors.black54 : Colors.white70
),
child: new DropDownButtonHideUnderline(child: label)
)
) )
) )
); );
......
...@@ -337,10 +337,8 @@ class DropDownMenuItem<T> extends StatelessWidget { ...@@ -337,10 +337,8 @@ class DropDownMenuItem<T> extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new Container( return new Container(
height: _kMenuItemHeight, height: _kMenuItemHeight,
child: new Align( align: FractionalOffset.centerLeft,
alignment: FractionalOffset.centerLeft, child: child
child: child
)
); );
} }
} }
......
...@@ -146,20 +146,18 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> { ...@@ -146,20 +146,18 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> {
); );
final bool effectiveCenterTitle = _getEffectiveCenterTitle(theme); final bool effectiveCenterTitle = _getEffectiveCenterTitle(theme);
final FractionalOffset titleAlignment = effectiveCenterTitle ? FractionalOffset.bottomCenter : FractionalOffset.bottomLeft; final FractionalOffset titleAlignment = effectiveCenterTitle ? FractionalOffset.bottomCenter : FractionalOffset.bottomLeft;
children.add(new Padding( children.add(new Container(
padding: new EdgeInsets.only(left: effectiveCenterTitle ? 0.0 : 72.0, bottom: 14.0), padding: new EdgeInsets.only(left: effectiveCenterTitle ? 0.0 : 72.0, bottom: 14.0),
child: new Align( align: new Tween<FractionalOffset>(
alignment: new Tween<FractionalOffset>( begin: new FractionalOffset(0.0, yAlignStart),
begin: new FractionalOffset(0.0, yAlignStart), end: new FractionalOffset(0.0, yAlignEnd)
end: new FractionalOffset(0.0, yAlignEnd) ).evaluate(scaleAndAlignCurve),
).evaluate(scaleAndAlignCurve), child: new ScaleTransition(
child: new ScaleTransition( alignment: titleAlignment,
scale: new Tween<double>(begin: 1.5, end: 1.0).animate(scaleAndAlignCurve),
child: new Align(
alignment: titleAlignment, alignment: titleAlignment,
scale: new Tween<double>(begin: 1.5, end: 1.0).animate(scaleAndAlignCurve), child: new DefaultTextStyle(style: titleStyle, child: config.title)
child: new Align(
alignment: titleAlignment,
child: new DefaultTextStyle(style: titleStyle, child: config.title)
)
) )
) )
)); ));
......
...@@ -154,10 +154,8 @@ class ListItem extends StatelessWidget { ...@@ -154,10 +154,8 @@ class ListItem extends StatelessWidget {
children.add(new Container( children.add(new Container(
margin: const EdgeInsets.only(right: 16.0), margin: const EdgeInsets.only(right: 16.0),
width: 40.0, width: 40.0,
child: new Align( align: FractionalOffset.centerLeft,
alignment: FractionalOffset.centerLeft, child: leading
child: leading
)
)); ));
} }
...@@ -188,10 +186,8 @@ class ListItem extends StatelessWidget { ...@@ -188,10 +186,8 @@ class ListItem extends StatelessWidget {
if (trailing != null) { if (trailing != null) {
children.add(new Container( children.add(new Container(
margin: const EdgeInsets.only(left: 16.0), margin: const EdgeInsets.only(left: 16.0),
child: new Align( align: FractionalOffset.centerRight,
alignment: FractionalOffset.centerRight, child: trailing
child: trailing
)
)); ));
} }
......
...@@ -370,22 +370,20 @@ class RefreshIndicatorState extends State<RefreshIndicator> { ...@@ -370,22 +370,20 @@ class RefreshIndicatorState extends State<RefreshIndicator> {
padding: _isIndicatorAtTop padding: _isIndicatorAtTop
? new EdgeInsets.only(top: config.displacement) ? new EdgeInsets.only(top: config.displacement)
: new EdgeInsets.only(bottom: config.displacement), : new EdgeInsets.only(bottom: config.displacement),
child: new Align( align: _isIndicatorAtTop
alignment: _isIndicatorAtTop ? FractionalOffset.bottomCenter
? FractionalOffset.bottomCenter : FractionalOffset.topCenter,
: FractionalOffset.topCenter, child: new ScaleTransition(
child: new ScaleTransition( scale: _scaleFactor,
scale: _scaleFactor, child: new AnimatedBuilder(
child: new AnimatedBuilder( animation: _sizeController,
animation: _sizeController, builder: (BuildContext context, Widget child) {
builder: (BuildContext context, Widget child) { return new RefreshProgressIndicator(
return new RefreshProgressIndicator( value: showIndeterminateIndicator ? null : _value.value,
value: showIndeterminateIndicator ? null : _value.value, valueColor: _valueColor,
valueColor: _valueColor, backgroundColor: config.backgroundColor
backgroundColor: config.backgroundColor );
); }
}
)
) )
) )
) )
......
...@@ -74,6 +74,7 @@ class Container extends StatelessWidget { ...@@ -74,6 +74,7 @@ class Container extends StatelessWidget {
/// Creates a widget that combines common painting, positioning, and sizing widgets. /// Creates a widget that combines common painting, positioning, and sizing widgets.
Container({ Container({
Key key, Key key,
this.align,
this.padding, this.padding,
this.decoration, this.decoration,
this.foregroundDecoration, this.foregroundDecoration,
...@@ -99,6 +100,12 @@ class Container extends StatelessWidget { ...@@ -99,6 +100,12 @@ class Container extends StatelessWidget {
/// If null, the container will expand to fill all available space in its parent. /// If null, the container will expand to fill all available space in its parent.
final Widget child; final Widget child;
/// Align the child within the container.
///
/// If non-null, the container will expand to fill its parent and position its
/// child within itself according to the given value.
final FractionalOffset align;
/// Empty space to inscribe inside the decoration. /// Empty space to inscribe inside the decoration.
final EdgeInsets padding; final EdgeInsets padding;
...@@ -133,6 +140,9 @@ class Container extends StatelessWidget { ...@@ -133,6 +140,9 @@ class Container extends StatelessWidget {
if (child == null && (constraints == null || !constraints.isTight)) if (child == null && (constraints == null || !constraints.isTight))
current = new ConstrainedBox(constraints: const BoxConstraints.expand()); current = new ConstrainedBox(constraints: const BoxConstraints.expand());
if (align != null)
current = new Align(alignment: align, child: current);
EdgeInsets effectivePadding = _paddingIncludingDecoration; EdgeInsets effectivePadding = _paddingIncludingDecoration;
if (effectivePadding != null) if (effectivePadding != null)
current = new Padding(padding: effectivePadding, child: current); current = new Padding(padding: effectivePadding, child: current);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment