Commit a5eb4c04 authored by Adam Barth's avatar Adam Barth

Remove ModalPosition (#3734)

Clients of getPosition should just use a one-child custom layout delegate
instead.

Fixes #2484
parent a5920c3d
...@@ -221,9 +221,8 @@ class GridListDemoState extends State<GridListDemo> { ...@@ -221,9 +221,8 @@ class GridListDemoState extends State<GridListDemo> {
]; ];
final EdgeInsets padding = MediaQuery.of(context).padding; final EdgeInsets padding = MediaQuery.of(context).padding;
final ModalPosition position = new ModalPosition( final RelativeRect position = new RelativeRect.fromLTRB(
right: padding.right + 16.0, 0.0, padding.top + 16.0, padding.right + 16.0, 0.0
top: padding.top + 16.0
); );
showMenu(context: context, position: position, items: items).then((GridDemoTileStyle value) { showMenu(context: context, position: position, items: items).then((GridDemoTileStyle value) {
......
...@@ -119,12 +119,12 @@ class _DropDownMenu<T> extends StatusTransitionWidget { ...@@ -119,12 +119,12 @@ class _DropDownMenu<T> extends StatusTransitionWidget {
); );
final Tween<double> menuTop = new Tween<double>( final Tween<double> menuTop = new Tween<double>(
begin: route.rect.top, begin: route.buttonRect.top,
end: route.rect.top - route.selectedIndex * route.rect.height - _kMenuVerticalPadding.top end: route.buttonRect.top - route.selectedIndex * route.buttonRect.height - _kMenuVerticalPadding.top
); );
final Tween<double> menuBottom = new Tween<double>( final Tween<double> menuBottom = new Tween<double>(
begin: route.rect.bottom, begin: route.buttonRect.bottom,
end: menuTop.end + route.items.length * route.rect.height + _kMenuVerticalPadding.vertical end: menuTop.end + route.items.length * route.buttonRect.height + _kMenuVerticalPadding.vertical
); );
Widget child = new Material( Widget child = new Material(
...@@ -156,6 +156,37 @@ class _DropDownMenu<T> extends StatusTransitionWidget { ...@@ -156,6 +156,37 @@ class _DropDownMenu<T> extends StatusTransitionWidget {
} }
} }
class _DropDownMenuRouteLayout extends SingleChildLayoutDelegate {
_DropDownMenuRouteLayout(this.buttonRect, this.selectedIndex);
final Rect buttonRect;
final int selectedIndex;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return new BoxConstraints(
minWidth: buttonRect.width,
maxWidth: buttonRect.width,
minHeight: 0.0,
maxHeight: constraints.maxHeight
);
}
@override
Offset getPositionForChild(Size size, Size childSize) {
return new Offset(
buttonRect.left,
buttonRect.top - selectedIndex * buttonRect.height - _kMenuVerticalPadding.top
);
}
@override
bool shouldRelayout(_DropDownMenuRouteLayout oldDelegate) {
return oldDelegate.buttonRect != buttonRect
|| oldDelegate.selectedIndex != selectedIndex;
}
}
// We box the return value so that the return value can be null. Otherwise, // We box the return value so that the return value can be null. Otherwise,
// canceling the route (which returns null) would get confused with actually // canceling the route (which returns null) would get confused with actually
// returning a real null value. // returning a real null value.
...@@ -180,14 +211,14 @@ class _DropDownRoute<T> extends PopupRoute<_DropDownRouteResult<T>> { ...@@ -180,14 +211,14 @@ class _DropDownRoute<T> extends PopupRoute<_DropDownRouteResult<T>> {
_DropDownRoute({ _DropDownRoute({
Completer<_DropDownRouteResult<T>> completer, Completer<_DropDownRouteResult<T>> completer,
this.items, this.items,
this.buttonRect,
this.selectedIndex, this.selectedIndex,
this.rect,
this.elevation: 8 this.elevation: 8
}) : super(completer: completer); }) : super(completer: completer);
final List<DropDownMenuItem<T>> items; final List<DropDownMenuItem<T>> items;
final Rect buttonRect;
final int selectedIndex; final int selectedIndex;
final Rect rect;
final int elevation; final int elevation;
@override @override
...@@ -199,22 +230,12 @@ class _DropDownRoute<T> extends PopupRoute<_DropDownRouteResult<T>> { ...@@ -199,22 +230,12 @@ class _DropDownRoute<T> extends PopupRoute<_DropDownRouteResult<T>> {
@override @override
Color get barrierColor => null; Color get barrierColor => null;
@override
ModalPosition getPosition(BuildContext context) {
RenderBox overlayBox = Overlay.of(context).context.findRenderObject();
assert(overlayBox != null); // can't be null; routes get inserted by Navigator which has its own Overlay
Size overlaySize = overlayBox.size;
RelativeRect menuRect = new RelativeRect.fromSize(rect, overlaySize);
return new ModalPosition(
top: menuRect.top - selectedIndex * rect.height - _kMenuVerticalPadding.top,
left: menuRect.left,
right: menuRect.right
);
}
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) {
return new _DropDownMenu<T>(route: this); return new CustomSingleChildLayout(
delegate: new _DropDownMenuRouteLayout(buttonRect, selectedIndex),
child: new _DropDownMenu<T>(route: this)
);
} }
} }
...@@ -359,13 +380,13 @@ class _DropDownButtonState<T> extends State<DropDownButton<T>> { ...@@ -359,13 +380,13 @@ class _DropDownButtonState<T> extends State<DropDownButton<T>> {
void _handleTap() { void _handleTap() {
final RenderBox renderBox = indexedStackKey.currentContext.findRenderObject(); final RenderBox renderBox = indexedStackKey.currentContext.findRenderObject();
final Rect rect = renderBox.localToGlobal(Point.origin) & renderBox.size; final Rect buttonRect = renderBox.localToGlobal(Point.origin) & renderBox.size;
final Completer<_DropDownRouteResult<T>> completer = new Completer<_DropDownRouteResult<T>>(); final Completer<_DropDownRouteResult<T>> completer = new Completer<_DropDownRouteResult<T>>();
Navigator.push(context, new _DropDownRoute<T>( Navigator.push(context, new _DropDownRoute<T>(
completer: completer, completer: completer,
items: config.items, items: config.items,
buttonRect: _kMenuHorizontalPadding.inflateRect(buttonRect),
selectedIndex: _selectedIndex, selectedIndex: _selectedIndex,
rect: _kMenuHorizontalPadding.inflateRect(rect),
elevation: config.elevation elevation: config.elevation
)); ));
completer.future.then((_DropDownRouteResult<T> newValue) { completer.future.then((_DropDownRouteResult<T> newValue) {
......
...@@ -328,17 +328,12 @@ class _PopupMenu<T> extends StatelessWidget { ...@@ -328,17 +328,12 @@ class _PopupMenu<T> extends StatelessWidget {
class _PopupMenuRouteLayout extends SingleChildLayoutDelegate { class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
_PopupMenuRouteLayout(this.position, this.selectedItemOffset); _PopupMenuRouteLayout(this.position, this.selectedItemOffset);
final ModalPosition position; final RelativeRect position;
final double selectedItemOffset; final double selectedItemOffset;
@override @override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) { BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return new BoxConstraints( return constraints.loosen();
minWidth: 0.0,
maxWidth: constraints.maxWidth,
minHeight: 0.0,
maxHeight: constraints.maxHeight
);
} }
// Put the child wherever position specifies, so long as it will fit within the // Put the child wherever position specifies, so long as it will fit within the
...@@ -380,14 +375,11 @@ class _PopupMenuRoute<T> extends PopupRoute<T> { ...@@ -380,14 +375,11 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
this.elevation this.elevation
}) : super(completer: completer); }) : super(completer: completer);
final ModalPosition position; final RelativeRect position;
final List<PopupMenuEntry<T>> items; final List<PopupMenuEntry<T>> items;
final dynamic initialValue; final dynamic initialValue;
final int elevation; final int elevation;
@override
ModalPosition getPosition(BuildContext context) => null;
@override @override
Animation<double> createAnimation() { Animation<double> createAnimation() {
return new CurvedAnimation( return new CurvedAnimation(
...@@ -416,13 +408,9 @@ class _PopupMenuRoute<T> extends PopupRoute<T> { ...@@ -416,13 +408,9 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
selectedItemOffset += items[i].height; selectedItemOffset += items[i].height;
} }
} }
final Size screenSize = MediaQuery.of(context).size; return new CustomSingleChildLayout(
return new ConstrainedBox( delegate: new _PopupMenuRouteLayout(position, selectedItemOffset),
constraints: new BoxConstraints(maxWidth: screenSize.width, maxHeight: screenSize.height), child: new _PopupMenu<T>(route: this)
child: new CustomSingleChildLayout(
delegate: new _PopupMenuRouteLayout(position, selectedItemOffset),
child: new _PopupMenu<T>(route: this)
)
); );
} }
} }
...@@ -434,7 +422,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> { ...@@ -434,7 +422,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
/// implies the menu's origin. /// implies the menu's origin.
Future<dynamic/*=T*/> showMenu/*<T>*/({ Future<dynamic/*=T*/> showMenu/*<T>*/({
BuildContext context, BuildContext context,
ModalPosition position, RelativeRect position,
List<PopupMenuEntry<dynamic/*=T*/>> items, List<PopupMenuEntry<dynamic/*=T*/>> items,
dynamic/*=T*/ initialValue, dynamic/*=T*/ initialValue,
int elevation: 8 int elevation: 8
...@@ -518,9 +506,9 @@ class _PopupMenuButtonState<T> extends State<PopupMenuButton<T>> { ...@@ -518,9 +506,9 @@ class _PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
elevation: config.elevation, elevation: config.elevation,
items: config.itemBuilder(context), items: config.itemBuilder(context),
initialValue: config.initialValue, initialValue: config.initialValue,
position: new ModalPosition( position: new RelativeRect.fromLTRB(
left: topLeft.x, topLeft.x, topLeft.y + (config.initialValue != null ? renderBox.size.height / 2.0 : 0.0),
top: topLeft.y + (config.initialValue != null ? renderBox.size.height / 2.0 : 0.0) 0.0, 0.0
) )
) )
.then((T value) { .then((T value) {
......
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