Unverified Commit f44b277f authored by jslavitz's avatar jslavitz Committed by GitHub

Custom offset functionality for Popup Menu Button (#22534)

* Adds offset functionality to popup menu
* Adds a test
parent aa6a27e8
......@@ -820,7 +820,9 @@ class PopupMenuButton<T> extends StatefulWidget {
this.padding = const EdgeInsets.all(8.0),
this.child,
this.icon,
this.offset = Offset.zero,
}) : assert(itemBuilder != null),
assert(offset != null),
assert(!(child != null && icon != null)), // fails if passed both parameters
super(key: key);
......@@ -864,6 +866,12 @@ class PopupMenuButton<T> extends StatefulWidget {
/// If provided, the icon used for this button.
final Icon icon;
/// The offset applied to the Popup Menu Button.
///
/// When not set, the Popup Menu Button will be positioned directly next to
/// the button that was used to create it.
final Offset offset;
@override
_PopupMenuButtonState<T> createState() => _PopupMenuButtonState<T>();
}
......@@ -874,7 +882,7 @@ class _PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
final RenderBox overlay = Overlay.of(context).context.findRenderObject();
final RelativeRect position = RelativeRect.fromRect(
Rect.fromPoints(
button.localToGlobal(Offset.zero, ancestor: overlay),
button.localToGlobal(widget.offset, ancestor: overlay),
button.localToGlobal(button.size.bottomRight(Offset.zero), ancestor: overlay),
),
Offset.zero & overlay.size,
......
......@@ -430,6 +430,45 @@ void main() {
expect(MediaQuery.of(popupContext).padding, EdgeInsets.zero);
});
testWidgets('Popup Menu Offset Test', (WidgetTester tester) async {
const Offset offset = Offset(100.0, 100.0);
final PopupMenuButton<int> popupMenuButton =
PopupMenuButton<int>(
offset: offset,
itemBuilder: (BuildContext context) {
return <PopupMenuItem<int>>[
PopupMenuItem<int>(
value: 1,
child: Builder(
builder: (BuildContext context) {
return const Text('AAA');
},
),
),
];
},
);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(
child: Material(
child: popupMenuButton,
),
)
),
),
);
await tester.tap(find.byType(IconButton));
await tester.pumpAndSettle();
// The position is different than the offset because the default position isn't at the origin.
expect(tester.getTopLeft(find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_PopupMenu<int>')), const Offset(364.0, 324.0));
});
testWidgets('open PopupMenu has correct semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(MaterialApp(
......
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