Remove ModalPosition (#3734)
Clients of getPosition should just use a one-child custom layout delegate instead. Fixes #2484
This commit is contained in:
parent
a5920c3d52
commit
a5eb4c04c7
@ -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 {
|
|||||||
);
|
);
|
||||||
|
|
||||||
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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>> {
|
|||||||
_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>> {
|
|||||||
@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>> {
|
|||||||
|
|
||||||
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 {
|
|||||||
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> {
|
|||||||
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> {
|
|||||||
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> {
|
|||||||
/// 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>> {
|
|||||||
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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user