diff --git a/examples/material_gallery/lib/demo/menu_demo.dart b/examples/material_gallery/lib/demo/menu_demo.dart index b8e76fe632..8632e17efd 100644 --- a/examples/material_gallery/lib/demo/menu_demo.dart +++ b/examples/material_gallery/lib/demo/menu_demo.dart @@ -111,7 +111,7 @@ class MenuDemoState extends State { primary: new Text('An item with a sectioned menu'), right: new PopupMenuButton( onSelected: showMenuSelection, - items: [ + items: >[ new PopupMenuItem( value: 'Preview', child: new ListItem( @@ -128,12 +128,12 @@ class MenuDemoState extends State { ), new PopupMenuItem( value: 'Get Link', - hasDivider: true, child: new ListItem( left: new Icon(icon: 'content/link'), primary: new Text('Get Link') ) ), + new PopupMenuDivider(), new PopupMenuItem( value: 'Remove', child: new ListItem( diff --git a/examples/material_gallery/lib/gallery/drawer.dart b/examples/material_gallery/lib/gallery/drawer.dart index 6836cfc3d4..cb2510beac 100644 --- a/examples/material_gallery/lib/gallery/drawer.dart +++ b/examples/material_gallery/lib/gallery/drawer.dart @@ -56,7 +56,7 @@ class GalleryDrawer extends StatelessComponent { ] ) ), - new DrawerDivider(), + new Divider(), new DrawerItem( icon: 'action/hourglass_empty', selected: timeDilation != 1.0, diff --git a/examples/stocks/lib/stock_home.dart b/examples/stocks/lib/stock_home.dart index ef04f85bb2..5b9af5cc58 100644 --- a/examples/stocks/lib/stock_home.dart +++ b/examples/stocks/lib/stock_home.dart @@ -169,7 +169,7 @@ class StockHomeState extends State { }, child: new Text('Dump App to Console') ), - new DrawerDivider(), + new Divider(), new DrawerItem( icon: 'action/thumb_up', onPressed: () => _handleStockModeChange(StockMode.optimistic), @@ -190,7 +190,7 @@ class StockHomeState extends State { ] ) ), - new DrawerDivider(), + new Divider(), new DrawerItem( icon: 'action/settings', onPressed: _handleShowSettings, diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart index 512619d07b..529651d55d 100644 --- a/examples/widgets/card_collection.dart +++ b/examples/widgets/card_collection.dart @@ -128,20 +128,20 @@ class CardCollectionState extends State { buildDrawerCheckbox("Fixed size cards", _fixedSizeCards, _toggleFixedSizeCards), buildDrawerCheckbox("Let the sun shine", _sunshine, _toggleSunshine), buildDrawerCheckbox("Vary font sizes", _varyFontSizes, _toggleVaryFontSizes, enabled: !_editable), - new DrawerDivider(), + new Divider(), buildDrawerColorRadioItem("Deep Purple", Colors.deepPurple, _primaryColor, _selectColor), buildDrawerColorRadioItem("Green", Colors.green, _primaryColor, _selectColor), buildDrawerColorRadioItem("Amber", Colors.amber, _primaryColor, _selectColor), buildDrawerColorRadioItem("Teal", Colors.teal, _primaryColor, _selectColor), - new DrawerDivider(), + new Divider(), buildDrawerDirectionRadioItem("Dismiss horizontally", DismissDirection.horizontal, _dismissDirection, _changeDismissDirection, icon: 'action/code'), buildDrawerDirectionRadioItem("Dismiss left", DismissDirection.left, _dismissDirection, _changeDismissDirection, icon: 'navigation/arrow_back'), buildDrawerDirectionRadioItem("Dismiss right", DismissDirection.right, _dismissDirection, _changeDismissDirection, icon: 'navigation/arrow_forward'), - new DrawerDivider(), + new Divider(), buildFontRadioItem("Left-align text", new TextStyle(textAlign: TextAlign.left), _textStyle, _changeTextStyle, icon: 'editor/format_align_left', enabled: !_editable), buildFontRadioItem("Center-align text", new TextStyle(textAlign: TextAlign.center), _textStyle, _changeTextStyle, icon: 'editor/format_align_center', enabled: !_editable), buildFontRadioItem("Right-align text", new TextStyle(textAlign: TextAlign.right), _textStyle, _changeTextStyle, icon: 'editor/format_align_right', enabled: !_editable), - new DrawerDivider(), + new Divider(), new DrawerItem( icon: 'device/dvr', onPressed: () { debugDumpApp(); debugDumpRenderTree(); }, diff --git a/packages/flutter/lib/material.dart b/packages/flutter/lib/material.dart index 2fcfa457d9..d6b0138e11 100644 --- a/packages/flutter/lib/material.dart +++ b/packages/flutter/lib/material.dart @@ -20,9 +20,9 @@ export 'src/material/date_picker.dart'; export 'src/material/date_picker_dialog.dart'; export 'src/material/dialog.dart'; export 'src/material/drawer.dart'; -export 'src/material/drawer_divider.dart'; export 'src/material/drawer_header.dart'; export 'src/material/drawer_item.dart'; +export 'src/material/divider.dart'; export 'src/material/dropdown.dart'; export 'src/material/flat_button.dart'; export 'src/material/flexible_space_bar.dart'; diff --git a/packages/flutter/lib/src/material/divider.dart b/packages/flutter/lib/src/material/divider.dart new file mode 100644 index 0000000000..0781e97fc0 --- /dev/null +++ b/packages/flutter/lib/src/material/divider.dart @@ -0,0 +1,34 @@ +// 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/widgets.dart'; + +import 'theme.dart'; + +class Divider extends StatelessComponent { + Divider({ Key key, this.height: 16.0, this.indent: 0.0, this.color }) : super(key: key) { + assert(height >= 1.0); + } + + final double height; + final double indent; + final Color color; + + Widget build(BuildContext context) { + final double bottom = (height ~/ 2.0).toDouble(); + return new Container( + height: 0.0, + margin: new EdgeDims.only( + top: height - bottom - 1.0, + left: indent, + bottom: bottom + ), + decoration: new BoxDecoration( + border: new Border( + bottom: new BorderSide(color: color ?? Theme.of(context).dividerColor) + ) + ) + ); + } +} diff --git a/packages/flutter/lib/src/material/drawer_divider.dart b/packages/flutter/lib/src/material/drawer_divider.dart deleted file mode 100644 index 4816892121..0000000000 --- a/packages/flutter/lib/src/material/drawer_divider.dart +++ /dev/null @@ -1,25 +0,0 @@ -// 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/widgets.dart'; - -import 'theme.dart'; - -class DrawerDivider extends StatelessComponent { - const DrawerDivider({ Key key }) : super(key: key); - - Widget build(BuildContext context) { - return new Container( - height: 0.0, - decoration: new BoxDecoration( - border: new Border( - bottom: new BorderSide( - color: Theme.of(context).dividerColor - ) - ) - ), - margin: const EdgeDims.symmetric(vertical: 8.0) - ); - } -} diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index 3b7dfa58bb..29b20a357a 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'package:flutter/widgets.dart'; +import 'divider.dart'; import 'icon.dart'; import 'icon_button.dart'; import 'icon_theme.dart'; @@ -26,20 +27,36 @@ const double _kMenuVerticalPadding = 8.0; const double _kMenuWidthStep = 56.0; const double _kMenuScreenPadding = 8.0; -class PopupMenuItem extends StatelessComponent { +abstract class PopupMenuEntry extends StatelessComponent { + PopupMenuEntry({ Key key }) : super(key: key); + + double get height; + T get value => null; + bool get enabled => true; +} + +class PopupMenuDivider extends PopupMenuEntry { + PopupMenuDivider({ Key key, this.height: 16.0 }) : super(key: key); + + final double height; + + Widget build(BuildContext context) => new Divider(height: height); +} + +class PopupMenuItem extends PopupMenuEntry { PopupMenuItem({ Key key, this.value, this.enabled: true, - this.hasDivider: false, this.child }) : super(key: key); final T value; final bool enabled; - final bool hasDivider; final Widget child; + double get height => _kMenuItemHeight; + Widget build(BuildContext context) { final ThemeData theme = Theme.of(context); TextStyle style = theme.text.subhead; @@ -49,7 +66,7 @@ class PopupMenuItem extends StatelessComponent { Widget item = new DefaultTextStyle( style: style, child: new Baseline( - baseline: _kMenuItemHeight - _kBaselineOffsetFromBottom, + baseline: height - _kBaselineOffsetFromBottom, child: child ) ); @@ -63,11 +80,8 @@ class PopupMenuItem extends StatelessComponent { return new MergeSemantics( child: new Container( - height: _kMenuItemHeight, + height: height, padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding), - decoration: !hasDivider ? null : new BoxDecoration( - border: new Border(bottom: new BorderSide(color: theme.dividerColor)) - ), child: item ) ); @@ -172,10 +186,10 @@ class _PopupMenu extends StatelessComponent { } class _PopupMenuRouteLayout extends OneChildLayoutDelegate { - _PopupMenuRouteLayout(this.position, this.selectedIndex); + _PopupMenuRouteLayout(this.position, this.selectedItemOffset); final ModalPosition position; - final int selectedIndex; + final double selectedItemOffset; BoxConstraints getConstraintsForChild(BoxConstraints constraints) { return new BoxConstraints( @@ -195,8 +209,8 @@ class _PopupMenuRouteLayout extends OneChildLayoutDelegate { double y = position?.top ?? (position?.bottom != null ? size.height - (position.bottom - childSize.height) : _kMenuScreenPadding); - if (selectedIndex != -1) - y -= (_kMenuItemHeight * selectedIndex) + _kMenuVerticalPadding + _kMenuItemHeight / 2.0; + if (selectedItemOffset != null) + y -= selectedItemOffset + _kMenuVerticalPadding + _kMenuItemHeight / 2.0; if (x < _kMenuScreenPadding) x = _kMenuScreenPadding; @@ -224,7 +238,7 @@ class _PopupMenuRoute extends PopupRoute { }) : super(completer: completer); final ModalPosition position; - final List> items; + final List> items; final dynamic initialValue; final int elevation; @@ -242,19 +256,20 @@ class _PopupMenuRoute extends PopupRoute { Color get barrierColor => null; Widget buildPage(BuildContext context, Animation animation, Animation forwardAnimation) { - int selectedIndex = -1; + double selectedItemOffset = null; if (initialValue != null) { - for (int i = 0; i < items.length; i++) - if (initialValue == items[i].value) { - selectedIndex = i; + selectedItemOffset = 0.0; + for (int i = 0; i < items.length; i++) { + if (initialValue == items[i].value) break; - } + selectedItemOffset += items[i].height; + } } final Size screenSize = MediaQuery.of(context).size; return new ConstrainedBox( constraints: new BoxConstraints(maxWidth: screenSize.width, maxHeight: screenSize.height), child: new CustomOneChildLayout( - delegate: new _PopupMenuRouteLayout(position, selectedIndex), + delegate: new _PopupMenuRouteLayout(position, selectedItemOffset), child: new _PopupMenu(route: this) ) ); @@ -269,7 +284,7 @@ class _PopupMenuRoute extends PopupRoute { Future/**/ showMenu/**/({ BuildContext context, ModalPosition position, - List*/> items, + List*/> items, dynamic/*=T*/ initialValue, int elevation: 8 }) { @@ -305,7 +320,7 @@ class PopupMenuButton extends StatefulComponent { this.child }) : super(key: key); - final List> items; + final List> items; final T initialValue; final PopupMenuItemSelected onSelected; final String tooltip;