diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart index 5ebfff02c0..8142b16b35 100644 --- a/examples/widgets/card_collection.dart +++ b/examples/widgets/card_collection.dart @@ -38,7 +38,7 @@ class CardCollectionState extends State { List _cardModels; DismissDirection _dismissDirection = DismissDirection.horizontal; TextStyle _textStyle = new TextStyle(textAlign: TextAlign.center); - bool _editable = true; + bool _editable = false; bool _snapToCenter = false; bool _fixedSizeCards = false; bool _sunshine = false; @@ -268,10 +268,16 @@ class CardCollectionState extends State { Widget buildToolBar() { return new ToolBar( left: new IconButton(icon: "navigation/menu", onPressed: _showDrawer), - center: new Text('Swipe Away'), right: [ new Text(_dismissDirectionText(_dismissDirection)) - ] + ], + bottom: new Padding( + padding: const EdgeDims.only(left: 72.0), + child: new Align( + alignment: const FractionalOffset(0.0, 0.5), + child: new Text('Swipe Away: ${_cardModels.length}') + ) + ) ); } diff --git a/packages/flutter/lib/src/material/constants.dart b/packages/flutter/lib/src/material/constants.dart index 6824793b97..a996fc5736 100644 --- a/packages/flutter/lib/src/material/constants.dart +++ b/packages/flutter/lib/src/material/constants.dart @@ -14,6 +14,7 @@ const double kStatusBarHeight = 50.0; // Mobile Portrait: 56dp // Tablet/Desktop: 64dp const double kToolBarHeight = 56.0; +const double kExtendedToolBarHeight = 128.0; const double kSnackBarHeight = 52.0; // https://www.google.com/design/spec/layout/metrics-keylines.html#metrics-keylines-keylines-spacing diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index cc975a567e..d40698022e 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -218,18 +218,18 @@ class DropdownButton extends StatelessComponent { return new GestureDetector( child: new Container( decoration: new BoxDecoration(border: _kDropdownUnderline), - child: new IntrinsicWidth( - child: new Row([ - new IndexedStack(items, - key: indexedStackKey, - index: selectedIndex, - alignment: const FractionalOffset(0.5, 0.0) - ), - new Container( - child: new Icon(icon: 'navigation/arrow_drop_down', size: IconSize.s36), - padding: const EdgeDims.only(top: 6.0) - ) - ]) + child: new Row([ + new IndexedStack(items, + key: indexedStackKey, + index: selectedIndex, + alignment: const FractionalOffset(0.5, 0.0) + ), + new Container( + child: new Icon(icon: 'navigation/arrow_drop_down', size: IconSize.s36), + padding: const EdgeDims.only(top: 6.0) + ) + ], + justifyContent: FlexJustifyContent.collapse ) ), onTap: () { diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index 5d735bfdb1..d3c8b13f67 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -4,92 +4,88 @@ import 'dart:ui' as ui; +import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'constants.dart'; import 'material.dart'; +import 'tool_bar.dart'; + +const int _kBodyIndex = 0; +const int _kToolBarIndex = 1; + +// This layout has the same effect as putting the toolbar and body in a column +// and making the body flexible. What's different is that in this case the +// toolbar appears -after- the body in the stacking order, so the toolbar's +// shadow is drawn on top of the body. +class _ToolBarAndBodyLayout extends MultiChildLayoutDelegate { + void performLayout(Size size, BoxConstraints constraints, int childCount) { + assert(childCount == 2); + final BoxConstraints toolBarConstraints = constraints.loosen().tightenWidth(size.width); + final Size toolBarSize = layoutChild(_kToolBarIndex, toolBarConstraints); + final double bodyHeight = size.height - toolBarSize.height; + final BoxConstraints bodyConstraints = toolBarConstraints.tightenHeight(bodyHeight); + layoutChild(_kBodyIndex, bodyConstraints); + positionChild(_kToolBarIndex, Point.origin); + positionChild(_kBodyIndex, new Point(0.0, toolBarSize.height)); + } +} + +final _ToolBarAndBodyLayout _toolBarAndBodyLayout = new _ToolBarAndBodyLayout(); class Scaffold extends StatelessComponent { Scaffold({ Key key, this.body, - this.statusBar, this.toolBar, this.snackBar, this.floatingActionButton }) : super(key: key); final Widget body; - final Widget statusBar; - final Widget toolBar; + final ToolBar toolBar; final Widget snackBar; final Widget floatingActionButton; Widget build(BuildContext context) { - double toolBarHeight = 0.0; - if (toolBar != null) - toolBarHeight = kToolBarHeight + ui.window.padding.top; + final ToolBar paddedToolBar = toolBar?.withPadding(new EdgeDims.only(top: ui.window.padding.top)); + final Widget materialBody = body != null ? new Material(child: body) : null; + Widget toolBarAndBody; + if (paddedToolBar != null && materialBody != null) + toolBarAndBody = new CustomMultiChildLayout([materialBody, paddedToolBar], + delegate: _toolBarAndBodyLayout + ); + else + toolBarAndBody = paddedToolBar ?? materialBody; - double statusBarHeight = 0.0; - if (statusBar != null) - statusBarHeight = kStatusBarHeight; + final List bottomColumnChildren = []; - List children = []; + if (floatingActionButton != null) + bottomColumnChildren.add(new Padding( + // TODO(eseidel): These change based on device size! + padding: const EdgeDims.only(right: 16.0, bottom: 16.0), + child: floatingActionButton + )); - if (body != null) { - children.add(new Positioned( - top: toolBarHeight, right: 0.0, bottom: statusBarHeight, left: 0.0, - child: new Material( - child: body - ) + // TODO(jackson): On tablet/desktop, minWidth = 288, maxWidth = 568 + if (snackBar != null) { + bottomColumnChildren.add(new ConstrainedBox( + constraints: const BoxConstraints(maxHeight: kSnackBarHeight), + child: snackBar )); } - if (statusBar != null) { - children.add(new Positioned( - right: 0.0, bottom: 0.0, left: 0.0, - child: new SizedBox( - height: statusBarHeight, - child: statusBar - ) + final List stackChildren = [toolBarAndBody]; + + if (bottomColumnChildren.length > 0) { + stackChildren.add(new Positioned( + right: 0.0, + left: 0.0, + bottom: 0.0, + child: new Column(bottomColumnChildren, alignItems: FlexAlignItems.end) )); } - if (toolBar != null) { - children.add(new Positioned( - top: 0.0, right: 0.0, left: 0.0, - child: new SizedBox( - height: toolBarHeight, - child: toolBar - ) - )); - } - - if (snackBar != null || floatingActionButton != null) { - List floatingChildren = []; - - if (floatingActionButton != null) { - floatingChildren.add(new Padding( - // TODO(eseidel): These change based on device size! - padding: const EdgeDims.only(right: 16.0, bottom: 16.0), - child: floatingActionButton - )); - } - - // TODO(jackson): On tablet/desktop, minWidth = 288, maxWidth = 568 - if (snackBar != null) { - floatingChildren.add(new ConstrainedBox( - constraints: const BoxConstraints(maxHeight: kSnackBarHeight), - child: snackBar - )); - } - - children.add(new Positioned( - right: 0.0, bottom: statusBarHeight, left: 0.0, - child: new Column(floatingChildren, alignItems: FlexAlignItems.end) - )); - } - - return new Stack(children); + return new Stack(stackChildren); } } diff --git a/packages/flutter/lib/src/material/tool_bar.dart b/packages/flutter/lib/src/material/tool_bar.dart index c4ac519c5a..1f38053032 100644 --- a/packages/flutter/lib/src/material/tool_bar.dart +++ b/packages/flutter/lib/src/material/tool_bar.dart @@ -17,17 +17,35 @@ class ToolBar extends StatelessComponent { this.left, this.center, this.right, + this.bottom, this.level: 2, this.backgroundColor, - this.textTheme + this.textTheme, + this.padding: EdgeDims.zero }) : super(key: key); final Widget left; final Widget center; final List right; + final Widget bottom; final int level; final Color backgroundColor; final TextTheme textTheme; + final EdgeDims padding; + + ToolBar withPadding(EdgeDims newPadding) { + return new ToolBar( + key: key, + left: left, + center: center, + right: right, + bottom: bottom, + level: level, + backgroundColor: backgroundColor, + textTheme: textTheme, + padding: newPadding + ); + } Widget build(BuildContext context) { Color color = backgroundColor; @@ -62,6 +80,16 @@ class ToolBar extends StatelessComponent { if (right != null) children.addAll(right); + final List columnChildren = [ + new Container(height: kToolBarHeight, child: new Row(children)) + ]; + + if (bottom != null) + columnChildren.add(new DefaultTextStyle( + style: centerStyle, + child: new Container(height: kExtendedToolBarHeight - kToolBarHeight, child: bottom) + )); + Widget content = new AnimatedContainer( duration: kThemeChangeDuration, padding: new EdgeDims.symmetric(horizontal: 8.0), @@ -71,14 +99,7 @@ class ToolBar extends StatelessComponent { ), child: new DefaultTextStyle( style: sideStyle, - child: new Column([ - new Container( - child: new Row(children), - height: kToolBarHeight - ), - ], - justifyContent: FlexJustifyContent.end - ) + child: new Container(padding: padding, child: new Column(columnChildren, justifyContent: FlexJustifyContent.collapse)) ) );