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> {
];
final EdgeInsets padding = MediaQuery.of(context).padding;
final ModalPosition position = new ModalPosition(
right: padding.right + 16.0,
top: padding.top + 16.0
final RelativeRect position = new RelativeRect.fromLTRB(
0.0, padding.top + 16.0, padding.right + 16.0, 0.0
);
showMenu(context: context, position: position, items: items).then((GridDemoTileStyle value) {
......
......@@ -119,12 +119,12 @@ class _DropDownMenu<T> extends StatusTransitionWidget {
);
final Tween<double> menuTop = new Tween<double>(
begin: route.rect.top,
end: route.rect.top - route.selectedIndex * route.rect.height - _kMenuVerticalPadding.top
begin: route.buttonRect.top,
end: route.buttonRect.top - route.selectedIndex * route.buttonRect.height - _kMenuVerticalPadding.top
);
final Tween<double> menuBottom = new Tween<double>(
begin: route.rect.bottom,
end: menuTop.end + route.items.length * route.rect.height + _kMenuVerticalPadding.vertical
begin: route.buttonRect.bottom,
end: menuTop.end + route.items.length * route.buttonRect.height + _kMenuVerticalPadding.vertical
);
Widget child = new Material(
......@@ -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,
// canceling the route (which returns null) would get confused with actually
// returning a real null value.
......@@ -180,14 +211,14 @@ class _DropDownRoute<T> extends PopupRoute<_DropDownRouteResult<T>> {
_DropDownRoute({
Completer<_DropDownRouteResult<T>> completer,
this.items,
this.buttonRect,
this.selectedIndex,
this.rect,
this.elevation: 8
}) : super(completer: completer);
final List<DropDownMenuItem<T>> items;
final Rect buttonRect;
final int selectedIndex;
final Rect rect;
final int elevation;
@override
......@@ -199,22 +230,12 @@ class _DropDownRoute<T> extends PopupRoute<_DropDownRouteResult<T>> {
@override
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
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>> {
void _handleTap() {
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>>();
Navigator.push(context, new _DropDownRoute<T>(
completer: completer,
items: config.items,
buttonRect: _kMenuHorizontalPadding.inflateRect(buttonRect),
selectedIndex: _selectedIndex,
rect: _kMenuHorizontalPadding.inflateRect(rect),
elevation: config.elevation
));
completer.future.then((_DropDownRouteResult<T> newValue) {
......
......@@ -328,17 +328,12 @@ class _PopupMenu<T> extends StatelessWidget {
class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
_PopupMenuRouteLayout(this.position, this.selectedItemOffset);
final ModalPosition position;
final RelativeRect position;
final double selectedItemOffset;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return new BoxConstraints(
minWidth: 0.0,
maxWidth: constraints.maxWidth,
minHeight: 0.0,
maxHeight: constraints.maxHeight
);
return constraints.loosen();
}
// Put the child wherever position specifies, so long as it will fit within the
......@@ -380,14 +375,11 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
this.elevation
}) : super(completer: completer);
final ModalPosition position;
final RelativeRect position;
final List<PopupMenuEntry<T>> items;
final dynamic initialValue;
final int elevation;
@override
ModalPosition getPosition(BuildContext context) => null;
@override
Animation<double> createAnimation() {
return new CurvedAnimation(
......@@ -416,13 +408,9 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
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 CustomSingleChildLayout(
return new CustomSingleChildLayout(
delegate: new _PopupMenuRouteLayout(position, selectedItemOffset),
child: new _PopupMenu<T>(route: this)
)
);
}
}
......@@ -434,7 +422,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
/// implies the menu's origin.
Future<dynamic/*=T*/> showMenu/*<T>*/({
BuildContext context,
ModalPosition position,
RelativeRect position,
List<PopupMenuEntry<dynamic/*=T*/>> items,
dynamic/*=T*/ initialValue,
int elevation: 8
......@@ -518,9 +506,9 @@ class _PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
elevation: config.elevation,
items: config.itemBuilder(context),
initialValue: config.initialValue,
position: new ModalPosition(
left: topLeft.x,
top: topLeft.y + (config.initialValue != null ? renderBox.size.height / 2.0 : 0.0)
position: new RelativeRect.fromLTRB(
topLeft.x, topLeft.y + (config.initialValue != null ? renderBox.size.height / 2.0 : 0.0),
0.0, 0.0
)
)
.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