Revert "Reland "Update PopupMenuButton to match Material Design spec"" (#75338)
This commit is contained in:
parent
f69f06e542
commit
7aa17231ac
@ -409,14 +409,8 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Popup Menu has correct Android semantics', () async {
|
test('Popup Menu has correct Android semantics', () async {
|
||||||
final SerializableFinder button = find.descendant(
|
|
||||||
of: find.byValueKey(popupButtonKeyValue),
|
|
||||||
matching: find.byType('Semantics'),
|
|
||||||
firstMatchOnly: true,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await getSemantics(button),
|
await getSemantics(find.byValueKey(popupButtonKeyValue)),
|
||||||
hasAndroidSemantics(
|
hasAndroidSemantics(
|
||||||
className: AndroidClassName.button,
|
className: AndroidClassName.button,
|
||||||
isChecked: false,
|
isChecked: false,
|
||||||
@ -438,21 +432,20 @@ void main() {
|
|||||||
|
|
||||||
for (final String item in popupItems) {
|
for (final String item in popupItems) {
|
||||||
expect(
|
expect(
|
||||||
await getSemantics(find.byValueKey('$popupKeyValue.$item')),
|
await getSemantics(find.byValueKey('$popupKeyValue.$item')),
|
||||||
hasAndroidSemantics(
|
hasAndroidSemantics(
|
||||||
className: AndroidClassName.button,
|
className: AndroidClassName.button,
|
||||||
isChecked: false,
|
isChecked: false,
|
||||||
isCheckable: false,
|
isCheckable: false,
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
isFocusable: true,
|
isFocusable: true,
|
||||||
actions: <AndroidSemanticsAction>[
|
actions: <AndroidSemanticsAction>[
|
||||||
if (item == popupItems.first) AndroidSemanticsAction.clearAccessibilityFocus,
|
if (item == popupItems.first) AndroidSemanticsAction.clearAccessibilityFocus,
|
||||||
if (item != popupItems.first) AndroidSemanticsAction.accessibilityFocus,
|
if (item != popupItems.first) AndroidSemanticsAction.accessibilityFocus,
|
||||||
AndroidSemanticsAction.click,
|
AndroidSemanticsAction.click,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
reason: "Popup $item doesn't have the right semantics",
|
reason: "Popup $item doesn't have the right semantics");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
await driver.tap(find.byValueKey('$popupKeyValue.${popupItems.first}'));
|
await driver.tap(find.byValueKey('$popupKeyValue.${popupItems.first}'));
|
||||||
|
|
||||||
|
@ -599,15 +599,7 @@ class _PopupMenu<T> extends StatelessWidget {
|
|||||||
|
|
||||||
// Positioning of the menu on the screen.
|
// Positioning of the menu on the screen.
|
||||||
class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
|
class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
|
||||||
_PopupMenuRouteLayout(
|
_PopupMenuRouteLayout(this.position, this.itemSizes, this.selectedItemIndex, this.textDirection);
|
||||||
this.position,
|
|
||||||
this.itemSizes,
|
|
||||||
this.selectedItemIndex,
|
|
||||||
this.textDirection,
|
|
||||||
this.topPadding,
|
|
||||||
this.bottomPadding,
|
|
||||||
this.placement,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Rectangle of underlying button, relative to the overlay's dimensions.
|
// Rectangle of underlying button, relative to the overlay's dimensions.
|
||||||
final RelativeRect position;
|
final RelativeRect position;
|
||||||
@ -623,15 +615,6 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
|
|||||||
// Whether to prefer going to the left or to the right.
|
// Whether to prefer going to the left or to the right.
|
||||||
final TextDirection textDirection;
|
final TextDirection textDirection;
|
||||||
|
|
||||||
// Top padding of unsafe area.
|
|
||||||
final double topPadding;
|
|
||||||
|
|
||||||
// Bottom padding of unsafe area.
|
|
||||||
final double bottomPadding;
|
|
||||||
|
|
||||||
// The placement of the menu.
|
|
||||||
final PopupMenuPlacement placement;
|
|
||||||
|
|
||||||
// We put the child wherever position specifies, so long as it will fit within
|
// We put the child wherever position specifies, so long as it will fit within
|
||||||
// the specified parent size padded (inset) by 8. If necessary, we adjust the
|
// the specified parent size padded (inset) by 8. If necessary, we adjust the
|
||||||
// child's position so that it fits.
|
// child's position so that it fits.
|
||||||
@ -641,8 +624,7 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
|
|||||||
// The menu can be at most the size of the overlay minus 8.0 pixels in each
|
// The menu can be at most the size of the overlay minus 8.0 pixels in each
|
||||||
// direction.
|
// direction.
|
||||||
return BoxConstraints.loose(
|
return BoxConstraints.loose(
|
||||||
constraints.biggest - Offset(_kMenuScreenPadding * 2.0,
|
constraints.biggest - const Offset(_kMenuScreenPadding * 2.0, _kMenuScreenPadding * 2.0) as Size,
|
||||||
_kMenuScreenPadding * 2.0 + topPadding + bottomPadding) as Size,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,23 +634,14 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
|
|||||||
// childSize: The size of the menu, when fully open, as determined by
|
// childSize: The size of the menu, when fully open, as determined by
|
||||||
// getConstraintsForChild.
|
// getConstraintsForChild.
|
||||||
|
|
||||||
final double buttonHeight = size.height - position.top - position.bottom;
|
|
||||||
|
|
||||||
// Find the ideal vertical position.
|
// Find the ideal vertical position.
|
||||||
// Default vertical position is below the element that generates it.
|
double y = position.top;
|
||||||
double y = placement == PopupMenuPlacement.belowButton
|
|
||||||
? position.top + buttonHeight
|
|
||||||
: position.top;
|
|
||||||
if (selectedItemIndex != null && itemSizes != null) {
|
if (selectedItemIndex != null && itemSizes != null) {
|
||||||
double selectedItemOffset = _kMenuVerticalPadding;
|
double selectedItemOffset = _kMenuVerticalPadding;
|
||||||
for (int index = 0; index < selectedItemIndex!; index += 1)
|
for (int index = 0; index < selectedItemIndex!; index += 1)
|
||||||
selectedItemOffset += itemSizes[index]!.height;
|
selectedItemOffset += itemSizes[index]!.height;
|
||||||
selectedItemOffset += itemSizes[selectedItemIndex!]!.height / 2;
|
selectedItemOffset += itemSizes[selectedItemIndex!]!.height / 2;
|
||||||
if (placement == PopupMenuPlacement.belowButton) {
|
y = position.top + (size.height - position.top - position.bottom) / 2.0 - selectedItemOffset;
|
||||||
y = y - buttonHeight / 2.0 - selectedItemOffset;
|
|
||||||
} else {
|
|
||||||
y = y + buttonHeight / 2.0 - selectedItemOffset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the ideal horizontal position.
|
// Find the ideal horizontal position.
|
||||||
@ -698,10 +671,10 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
|
|||||||
x = _kMenuScreenPadding;
|
x = _kMenuScreenPadding;
|
||||||
else if (x + childSize.width > size.width - _kMenuScreenPadding)
|
else if (x + childSize.width > size.width - _kMenuScreenPadding)
|
||||||
x = size.width - childSize.width - _kMenuScreenPadding;
|
x = size.width - childSize.width - _kMenuScreenPadding;
|
||||||
if (y < _kMenuScreenPadding + topPadding)
|
if (y < _kMenuScreenPadding)
|
||||||
y = _kMenuScreenPadding + topPadding;
|
y = _kMenuScreenPadding;
|
||||||
else if (y + childSize.height > size.height - _kMenuScreenPadding)
|
else if (y + childSize.height > size.height - _kMenuScreenPadding)
|
||||||
y = size.height - bottomPadding - _kMenuScreenPadding - childSize.height ;
|
y = size.height - childSize.height - _kMenuScreenPadding;
|
||||||
return Offset(x, y);
|
return Offset(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,9 +686,9 @@ class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
|
|||||||
assert(itemSizes.length == oldDelegate.itemSizes.length);
|
assert(itemSizes.length == oldDelegate.itemSizes.length);
|
||||||
|
|
||||||
return position != oldDelegate.position
|
return position != oldDelegate.position
|
||||||
|| selectedItemIndex != oldDelegate.selectedItemIndex
|
|| selectedItemIndex != oldDelegate.selectedItemIndex
|
||||||
|| textDirection != oldDelegate.textDirection
|
|| textDirection != oldDelegate.textDirection
|
||||||
|| !listEquals(itemSizes, oldDelegate.itemSizes);
|
|| !listEquals(itemSizes, oldDelegate.itemSizes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,7 +703,6 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
|
|||||||
this.shape,
|
this.shape,
|
||||||
this.color,
|
this.color,
|
||||||
required this.capturedThemes,
|
required this.capturedThemes,
|
||||||
required this.placement,
|
|
||||||
}) : itemSizes = List<Size?>.filled(items.length, null);
|
}) : itemSizes = List<Size?>.filled(items.length, null);
|
||||||
|
|
||||||
final RelativeRect position;
|
final RelativeRect position;
|
||||||
@ -742,7 +714,6 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
|
|||||||
final ShapeBorder? shape;
|
final ShapeBorder? shape;
|
||||||
final Color? color;
|
final Color? color;
|
||||||
final CapturedThemes capturedThemes;
|
final CapturedThemes capturedThemes;
|
||||||
final PopupMenuPlacement placement;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Animation<double> createAnimation() {
|
Animation<double> createAnimation() {
|
||||||
@ -778,22 +749,20 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
|
|||||||
|
|
||||||
final Widget menu = _PopupMenu<T>(route: this, semanticLabel: semanticLabel);
|
final Widget menu = _PopupMenu<T>(route: this, semanticLabel: semanticLabel);
|
||||||
|
|
||||||
return Builder(
|
return SafeArea(
|
||||||
builder: (BuildContext context) {
|
child: Builder(
|
||||||
final MediaQueryData mediaQuery = MediaQuery.of(context);
|
builder: (BuildContext context) {
|
||||||
return CustomSingleChildLayout(
|
return CustomSingleChildLayout(
|
||||||
delegate: _PopupMenuRouteLayout(
|
delegate: _PopupMenuRouteLayout(
|
||||||
position,
|
position,
|
||||||
itemSizes,
|
itemSizes,
|
||||||
selectedItemIndex,
|
selectedItemIndex,
|
||||||
Directionality.of(context),
|
Directionality.of(context),
|
||||||
mediaQuery.padding.top,
|
),
|
||||||
mediaQuery.padding.bottom,
|
child: capturedThemes.wrap(menu),
|
||||||
placement,
|
);
|
||||||
),
|
},
|
||||||
child: capturedThemes.wrap(menu),
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -863,7 +832,6 @@ Future<T?> showMenu<T>({
|
|||||||
ShapeBorder? shape,
|
ShapeBorder? shape,
|
||||||
Color? color,
|
Color? color,
|
||||||
bool useRootNavigator = false,
|
bool useRootNavigator = false,
|
||||||
PopupMenuPlacement placement = PopupMenuPlacement.aboveButton,
|
|
||||||
}) {
|
}) {
|
||||||
assert(context != null);
|
assert(context != null);
|
||||||
assert(position != null);
|
assert(position != null);
|
||||||
@ -893,7 +861,6 @@ Future<T?> showMenu<T>({
|
|||||||
shape: shape,
|
shape: shape,
|
||||||
color: color,
|
color: color,
|
||||||
capturedThemes: InheritedTheme.capture(from: context, to: navigator.context),
|
capturedThemes: InheritedTheme.capture(from: context, to: navigator.context),
|
||||||
placement: placement,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -916,17 +883,6 @@ typedef PopupMenuCanceled = void Function();
|
|||||||
/// Used by [PopupMenuButton.itemBuilder].
|
/// Used by [PopupMenuButton.itemBuilder].
|
||||||
typedef PopupMenuItemBuilder<T> = List<PopupMenuEntry<T>> Function(BuildContext context);
|
typedef PopupMenuItemBuilder<T> = List<PopupMenuEntry<T>> Function(BuildContext context);
|
||||||
|
|
||||||
/// The placement of the menu popped up by press the [PopupMenuButton].
|
|
||||||
///
|
|
||||||
/// Used by [PopupMenuButton.placement].
|
|
||||||
enum PopupMenuPlacement {
|
|
||||||
/// The popup menu is positioned above the button that generates it.
|
|
||||||
aboveButton,
|
|
||||||
|
|
||||||
/// The popup menu is positioned below the button that generates it.
|
|
||||||
belowButton,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Displays a menu when pressed and calls [onSelected] when the menu is dismissed
|
/// Displays a menu when pressed and calls [onSelected] when the menu is dismissed
|
||||||
/// because an item was selected. The value passed to [onSelected] is the value of
|
/// because an item was selected. The value passed to [onSelected] is the value of
|
||||||
/// the selected menu item.
|
/// the selected menu item.
|
||||||
@ -999,7 +955,6 @@ class PopupMenuButton<T> extends StatefulWidget {
|
|||||||
this.shape,
|
this.shape,
|
||||||
this.color,
|
this.color,
|
||||||
this.enableFeedback,
|
this.enableFeedback,
|
||||||
this.placement = PopupMenuPlacement.aboveButton,
|
|
||||||
}) : assert(itemBuilder != null),
|
}) : assert(itemBuilder != null),
|
||||||
assert(offset != null),
|
assert(offset != null),
|
||||||
assert(enabled != null),
|
assert(enabled != null),
|
||||||
@ -1051,7 +1006,7 @@ class PopupMenuButton<T> extends StatefulWidget {
|
|||||||
|
|
||||||
/// The offset applied to the Popup Menu Button.
|
/// The offset applied to the Popup Menu Button.
|
||||||
///
|
///
|
||||||
/// When not set, the Popup Menu Button will be positioned directly below
|
/// When not set, the Popup Menu Button will be positioned directly next to
|
||||||
/// the button that was used to create it.
|
/// the button that was used to create it.
|
||||||
final Offset offset;
|
final Offset offset;
|
||||||
|
|
||||||
@ -1094,11 +1049,6 @@ class PopupMenuButton<T> extends StatefulWidget {
|
|||||||
/// * [Feedback] for providing platform-specific feedback to certain actions.
|
/// * [Feedback] for providing platform-specific feedback to certain actions.
|
||||||
final bool? enableFeedback;
|
final bool? enableFeedback;
|
||||||
|
|
||||||
/// The placement of the menu popped up by press the [PopupMenuButton].
|
|
||||||
///
|
|
||||||
/// Default to [PopupMenuPlacement.aboveButton].
|
|
||||||
final PopupMenuPlacement placement;
|
|
||||||
|
|
||||||
/// If provided, the size of the [Icon].
|
/// If provided, the size of the [Icon].
|
||||||
///
|
///
|
||||||
/// If this property is null, the default size is 24.0 pixels.
|
/// If this property is null, the default size is 24.0 pixels.
|
||||||
@ -1113,9 +1063,8 @@ class PopupMenuButton<T> extends StatefulWidget {
|
|||||||
/// See [showButtonMenu] for a way to programmatically open the popup menu
|
/// See [showButtonMenu] for a way to programmatically open the popup menu
|
||||||
/// of your button state.
|
/// of your button state.
|
||||||
class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
||||||
final GlobalKey _menuButtonKey = GlobalKey();
|
|
||||||
/// A method to show a popup menu with the items supplied to
|
/// A method to show a popup menu with the items supplied to
|
||||||
/// [PopupMenuButton.itemBuilder] at the position below your [PopupMenuButton].
|
/// [PopupMenuButton.itemBuilder] at the position of your [PopupMenuButton].
|
||||||
///
|
///
|
||||||
/// By default, it is called when the user taps the button and [PopupMenuButton.enabled]
|
/// By default, it is called when the user taps the button and [PopupMenuButton.enabled]
|
||||||
/// is set to `true`. Moreover, you can open the button by calling the method manually.
|
/// is set to `true`. Moreover, you can open the button by calling the method manually.
|
||||||
@ -1124,14 +1073,8 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
|||||||
/// show the menu of the button with `globalKey.currentState.showButtonMenu`.
|
/// show the menu of the button with `globalKey.currentState.showButtonMenu`.
|
||||||
void showButtonMenu() {
|
void showButtonMenu() {
|
||||||
final PopupMenuThemeData popupMenuTheme = PopupMenuTheme.of(context);
|
final PopupMenuThemeData popupMenuTheme = PopupMenuTheme.of(context);
|
||||||
|
final RenderBox button = context.findRenderObject()! as RenderBox;
|
||||||
final RenderBox overlay = Navigator.of(context).overlay!.context.findRenderObject()! as RenderBox;
|
final RenderBox overlay = Navigator.of(context).overlay!.context.findRenderObject()! as RenderBox;
|
||||||
final RenderBox button;
|
|
||||||
if (widget.placement == PopupMenuPlacement.belowButton) {
|
|
||||||
button = _menuButtonKey.currentContext!.findRenderObject()! as RenderBox;
|
|
||||||
} else {
|
|
||||||
// Backward compatible.
|
|
||||||
button = context.findRenderObject()! as RenderBox;
|
|
||||||
}
|
|
||||||
final RelativeRect position = RelativeRect.fromRect(
|
final RelativeRect position = RelativeRect.fromRect(
|
||||||
Rect.fromPoints(
|
Rect.fromPoints(
|
||||||
button.localToGlobal(widget.offset, ancestor: overlay),
|
button.localToGlobal(widget.offset, ancestor: overlay),
|
||||||
@ -1150,7 +1093,6 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
|||||||
position: position,
|
position: position,
|
||||||
shape: widget.shape ?? popupMenuTheme.shape,
|
shape: widget.shape ?? popupMenuTheme.shape,
|
||||||
color: widget.color ?? popupMenuTheme.color,
|
color: widget.color ?? popupMenuTheme.color,
|
||||||
placement: widget.placement,
|
|
||||||
)
|
)
|
||||||
.then<void>((T? newValue) {
|
.then<void>((T? newValue) {
|
||||||
if (!mounted)
|
if (!mounted)
|
||||||
@ -1190,40 +1132,18 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
|||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: widget.enabled ? showButtonMenu : null,
|
onTap: widget.enabled ? showButtonMenu : null,
|
||||||
canRequestFocus: _canRequestFocus,
|
canRequestFocus: _canRequestFocus,
|
||||||
|
child: widget.child,
|
||||||
enableFeedback: enableFeedback,
|
enableFeedback: enableFeedback,
|
||||||
child: LayoutBuilder(
|
|
||||||
builder: (BuildContext context, BoxConstraints constraints) {
|
|
||||||
return UnconstrainedBox(
|
|
||||||
constrainedAxis: Axis.horizontal,
|
|
||||||
child: LimitedBox(
|
|
||||||
key: _menuButtonKey,
|
|
||||||
maxHeight: constraints.maxHeight,
|
|
||||||
child: widget.child,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return LayoutBuilder(
|
return IconButton(
|
||||||
builder: (BuildContext context, BoxConstraints constraints) {
|
icon: widget.icon ?? Icon(Icons.adaptive.more),
|
||||||
return UnconstrainedBox(
|
padding: widget.padding,
|
||||||
constrainedAxis: Axis.horizontal,
|
iconSize: widget.iconSize ?? 24.0,
|
||||||
child: LimitedBox(
|
tooltip: widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip,
|
||||||
maxHeight: constraints.maxHeight,
|
onPressed: widget.enabled ? showButtonMenu : null,
|
||||||
child: IconButton(
|
enableFeedback: enableFeedback,
|
||||||
key: _menuButtonKey,
|
|
||||||
icon: widget.icon ?? Icon(Icons.adaptive.more),
|
|
||||||
padding: widget.padding,
|
|
||||||
iconSize: widget.iconSize ?? 24.0,
|
|
||||||
tooltip: widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip,
|
|
||||||
onPressed: widget.enabled ? showButtonMenu : null,
|
|
||||||
enableFeedback: enableFeedback,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,7 +453,6 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('PopupMenu positioning', (WidgetTester tester) async {
|
testWidgets('PopupMenu positioning', (WidgetTester tester) async {
|
||||||
final Widget testButton = PopupMenuButton<int>(
|
final Widget testButton = PopupMenuButton<int>(
|
||||||
placement: PopupMenuPlacement.belowButton,
|
|
||||||
itemBuilder: (BuildContext context) {
|
itemBuilder: (BuildContext context) {
|
||||||
return <PopupMenuItem<int>>[
|
return <PopupMenuItem<int>>[
|
||||||
const PopupMenuItem<int>(value: 1, child: Text('AAA')),
|
const PopupMenuItem<int>(value: 1, child: Text('AAA')),
|
||||||
@ -619,24 +618,24 @@ void main() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await testPositioningDown(tester, TextDirection.ltr, Alignment.topRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 100.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.ltr, Alignment.topRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 8.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.rtl, Alignment.topRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 100.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.rtl, Alignment.topRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 8.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.ltr, Alignment.topLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 100.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.ltr, Alignment.topLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 8.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.rtl, Alignment.topLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 100.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.rtl, Alignment.topLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 8.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.ltr, Alignment.topCenter, TextDirection.ltr, const Rect.fromLTWH(350.0, 100.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.ltr, Alignment.topCenter, TextDirection.ltr, const Rect.fromLTWH(350.0, 8.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.rtl, Alignment.topCenter, TextDirection.rtl, const Rect.fromLTWH(450.0, 100.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.rtl, Alignment.topCenter, TextDirection.rtl, const Rect.fromLTWH(450.0, 8.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.ltr, Alignment.centerRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 350.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.ltr, Alignment.centerRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 250.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.rtl, Alignment.centerRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 350.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.rtl, Alignment.centerRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 250.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.ltr, Alignment.centerLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 350.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.ltr, Alignment.centerLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 250.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.rtl, Alignment.centerLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 350.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.rtl, Alignment.centerLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 250.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.ltr, Alignment.center, TextDirection.ltr, const Rect.fromLTWH(350.0, 350.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.ltr, Alignment.center, TextDirection.ltr, const Rect.fromLTWH(350.0, 250.0, 0.0, 0.0));
|
||||||
await testPositioningDown(tester, TextDirection.rtl, Alignment.center, TextDirection.rtl, const Rect.fromLTWH(450.0, 350.0, 0.0, 0.0));
|
await testPositioningDown(tester, TextDirection.rtl, Alignment.center, TextDirection.rtl, const Rect.fromLTWH(450.0, 250.0, 0.0, 0.0));
|
||||||
await testPositioningDownThenUp(tester, TextDirection.ltr, Alignment.bottomRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 592.0, 0.0, 0.0));
|
await testPositioningDownThenUp(tester, TextDirection.ltr, Alignment.bottomRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 500.0, 0.0, 0.0));
|
||||||
await testPositioningDownThenUp(tester, TextDirection.rtl, Alignment.bottomRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 592.0, 0.0, 0.0));
|
await testPositioningDownThenUp(tester, TextDirection.rtl, Alignment.bottomRight, TextDirection.rtl, const Rect.fromLTWH(792.0, 500.0, 0.0, 0.0));
|
||||||
await testPositioningDownThenUp(tester, TextDirection.ltr, Alignment.bottomLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 592.0, 0.0, 0.0));
|
await testPositioningDownThenUp(tester, TextDirection.ltr, Alignment.bottomLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 500.0, 0.0, 0.0));
|
||||||
await testPositioningDownThenUp(tester, TextDirection.rtl, Alignment.bottomLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 592.0, 0.0, 0.0));
|
await testPositioningDownThenUp(tester, TextDirection.rtl, Alignment.bottomLeft, TextDirection.ltr, const Rect.fromLTWH(8.0, 500.0, 0.0, 0.0));
|
||||||
await testPositioningDownThenUp(tester, TextDirection.ltr, Alignment.bottomCenter, TextDirection.ltr, const Rect.fromLTWH(350.0, 592.0, 0.0, 0.0));
|
await testPositioningDownThenUp(tester, TextDirection.ltr, Alignment.bottomCenter, TextDirection.ltr, const Rect.fromLTWH(350.0, 500.0, 0.0, 0.0));
|
||||||
await testPositioningDownThenUp(tester, TextDirection.rtl, Alignment.bottomCenter, TextDirection.rtl, const Rect.fromLTWH(450.0, 592.0, 0.0, 0.0));
|
await testPositioningDownThenUp(tester, TextDirection.rtl, Alignment.bottomCenter, TextDirection.rtl, const Rect.fromLTWH(450.0, 500.0, 0.0, 0.0));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('PopupMenu positioning inside nested Overlay', (WidgetTester tester) async {
|
testWidgets('PopupMenu positioning inside nested Overlay', (WidgetTester tester) async {
|
||||||
@ -654,7 +653,6 @@ void main() {
|
|||||||
builder: (_) => Center(
|
builder: (_) => Center(
|
||||||
child: PopupMenuButton<int>(
|
child: PopupMenuButton<int>(
|
||||||
key: buttonKey,
|
key: buttonKey,
|
||||||
placement: PopupMenuPlacement.belowButton,
|
|
||||||
itemBuilder: (_) => <PopupMenuItem<int>>[
|
itemBuilder: (_) => <PopupMenuItem<int>>[
|
||||||
const PopupMenuItem<int>(value: 1, child: Text('Item 1')),
|
const PopupMenuItem<int>(value: 1, child: Text('Item 1')),
|
||||||
const PopupMenuItem<int>(value: 2, child: Text('Item 2')),
|
const PopupMenuItem<int>(value: 2, child: Text('Item 2')),
|
||||||
@ -675,8 +673,8 @@ void main() {
|
|||||||
await tester.tap(buttonFinder);
|
await tester.tap(buttonFinder);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final Offset buttonBottomLeft = tester.getBottomLeft(buttonFinder);
|
final Offset buttonTopLeft = tester.getTopLeft(buttonFinder);
|
||||||
expect(tester.getTopLeft(popupFinder), buttonBottomLeft);
|
expect(tester.getTopLeft(popupFinder), buttonTopLeft);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('PopupMenu positioning inside nested Navigator', (WidgetTester tester) async {
|
testWidgets('PopupMenu positioning inside nested Navigator', (WidgetTester tester) async {
|
||||||
@ -697,7 +695,6 @@ void main() {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: PopupMenuButton<int>(
|
child: PopupMenuButton<int>(
|
||||||
key: buttonKey,
|
key: buttonKey,
|
||||||
placement: PopupMenuPlacement.belowButton,
|
|
||||||
itemBuilder: (_) => <PopupMenuItem<int>>[
|
itemBuilder: (_) => <PopupMenuItem<int>>[
|
||||||
const PopupMenuItem<int>(value: 1, child: Text('Item 1')),
|
const PopupMenuItem<int>(value: 1, child: Text('Item 1')),
|
||||||
const PopupMenuItem<int>(value: 2, child: Text('Item 2')),
|
const PopupMenuItem<int>(value: 2, child: Text('Item 2')),
|
||||||
@ -720,8 +717,8 @@ void main() {
|
|||||||
await tester.tap(buttonFinder);
|
await tester.tap(buttonFinder);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final Offset buttonBottomLeft = tester.getBottomLeft(buttonFinder);
|
final Offset buttonTopLeft = tester.getTopLeft(buttonFinder);
|
||||||
expect(tester.getTopLeft(popupFinder), buttonBottomLeft);
|
expect(tester.getTopLeft(popupFinder), buttonTopLeft);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('PopupMenu removes MediaQuery padding', (WidgetTester tester) async {
|
testWidgets('PopupMenu removes MediaQuery padding', (WidgetTester tester) async {
|
||||||
@ -734,7 +731,6 @@ void main() {
|
|||||||
),
|
),
|
||||||
child: Material(
|
child: Material(
|
||||||
child: PopupMenuButton<int>(
|
child: PopupMenuButton<int>(
|
||||||
placement: PopupMenuPlacement.belowButton,
|
|
||||||
itemBuilder: (BuildContext context) {
|
itemBuilder: (BuildContext context) {
|
||||||
popupContext = context;
|
popupContext = context;
|
||||||
return <PopupMenuItem<int>>[
|
return <PopupMenuItem<int>>[
|
||||||
@ -769,7 +765,6 @@ void main() {
|
|||||||
testWidgets('Popup Menu Offset Test', (WidgetTester tester) async {
|
testWidgets('Popup Menu Offset Test', (WidgetTester tester) async {
|
||||||
PopupMenuButton<int> buildMenuButton({Offset offset = Offset.zero}) {
|
PopupMenuButton<int> buildMenuButton({Offset offset = Offset.zero}) {
|
||||||
return PopupMenuButton<int>(
|
return PopupMenuButton<int>(
|
||||||
placement: PopupMenuPlacement.belowButton,
|
|
||||||
offset: offset,
|
offset: offset,
|
||||||
itemBuilder: (BuildContext context) {
|
itemBuilder: (BuildContext context) {
|
||||||
return <PopupMenuItem<int>>[
|
return <PopupMenuItem<int>>[
|
||||||
@ -801,10 +796,8 @@ void main() {
|
|||||||
await tester.tap(find.byType(IconButton));
|
await tester.tap(find.byType(IconButton));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final Size iconSize = tester.getSize(find.byType(IconButton));
|
// Initial state, the menu start at Offset(8.0, 8.0), the 8 pixels is edge padding when offset.dx < 8.0.
|
||||||
|
expect(tester.getTopLeft(find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_PopupMenu<int?>')), const Offset(8.0, 8.0));
|
||||||
// Initial state, the menu start at bottomLeft of the icon, the 8 pixels is edge padding when offset.dx < 8.0.
|
|
||||||
expect(tester.getTopLeft(find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_PopupMenu<int?>')), Offset(8.0, iconSize.height));
|
|
||||||
|
|
||||||
// Collapse the menu.
|
// Collapse the menu.
|
||||||
await tester.tap(find.byType(IconButton), warnIfMissed: false);
|
await tester.tap(find.byType(IconButton), warnIfMissed: false);
|
||||||
@ -824,8 +817,8 @@ void main() {
|
|||||||
await tester.tap(find.byType(IconButton));
|
await tester.tap(find.byType(IconButton));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// This time the menu should start at Offset(50.0, 50.0 + iconSize.height), the padding only added when offset.dx < 8.0.
|
// This time the menu should start at Offset(50.0, 50.0), the padding only added when offset.dx < 8.0.
|
||||||
expect(tester.getTopLeft(find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_PopupMenu<int?>')), Offset(50.0, 50.0 + iconSize.height));
|
expect(tester.getTopLeft(find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_PopupMenu<int?>')), const Offset(50.0, 50.0));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('open PopupMenu has correct semantics', (WidgetTester tester) async {
|
testWidgets('open PopupMenu has correct semantics', (WidgetTester tester) async {
|
||||||
@ -1811,124 +1804,6 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('PopupMenu button can render at its "natural" size in AppBar', (WidgetTester tester) async {
|
|
||||||
final GlobalKey buttonKey = GlobalKey();
|
|
||||||
|
|
||||||
Widget buildFrame(double width, double height) {
|
|
||||||
return MaterialApp(
|
|
||||||
builder: (BuildContext context, Widget? child) {
|
|
||||||
return MediaQuery(
|
|
||||||
data: const MediaQueryData(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
top: 32.0,
|
|
||||||
bottom: 32.0,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: child!,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
home: Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
toolbarHeight: 100.0,
|
|
||||||
title: const Text('PopupMenu Test'),
|
|
||||||
actions: <Widget>[PopupMenuButton<int>(
|
|
||||||
child: SizedBox(
|
|
||||||
key: buttonKey,
|
|
||||||
height: height,
|
|
||||||
width: width,
|
|
||||||
child: const ColoredBox(
|
|
||||||
color: Colors.pink,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
itemBuilder: (BuildContext context) => <PopupMenuEntry<int>>[
|
|
||||||
const PopupMenuItem<int>(child: Text('-1-'), value: 1),
|
|
||||||
const PopupMenuItem<int>(child: Text('-2-'), value: 2),
|
|
||||||
const PopupMenuItem<int>(child: Text('-3-'), value: 3),
|
|
||||||
const PopupMenuItem<int>(child: Text('-4-'), value: 4),
|
|
||||||
const PopupMenuItem<int>(child: Text('-5-'), value: 5),
|
|
||||||
],
|
|
||||||
)],
|
|
||||||
),
|
|
||||||
body: Container(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await tester.pumpWidget(buildFrame(10.0, 10.0));
|
|
||||||
Size buttonSize = tester.getSize(find.byKey(buttonKey));
|
|
||||||
expect(buttonSize, const Size(10.0, 10.0));
|
|
||||||
|
|
||||||
await tester.pumpWidget(buildFrame(20.5, 30.5));
|
|
||||||
buttonSize = tester.getSize(find.byKey(buttonKey));
|
|
||||||
expect(buttonSize, const Size(20.5, 30.5));
|
|
||||||
|
|
||||||
await tester.pumpWidget(buildFrame(20.0, 100.0));
|
|
||||||
buttonSize = tester.getSize(find.byKey(buttonKey));
|
|
||||||
expect(buttonSize, const Size(20.0, 100.0));
|
|
||||||
|
|
||||||
await tester.pumpWidget(buildFrame(20.0, 100.1));
|
|
||||||
buttonSize = tester.getSize(find.byKey(buttonKey));
|
|
||||||
expect(buttonSize, const Size(20.0, 100.0)); // Do not overflow the AppBar.
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('PopupMenu position test when have unsafe area', (WidgetTester tester) async {
|
|
||||||
final GlobalKey buttonKey = GlobalKey();
|
|
||||||
final GlobalKey firstItemKey = GlobalKey();
|
|
||||||
|
|
||||||
Widget buildFrame(double width, double height) {
|
|
||||||
return MaterialApp(
|
|
||||||
builder: (BuildContext context, Widget? child) {
|
|
||||||
return MediaQuery(
|
|
||||||
data: const MediaQueryData(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
top: 32.0,
|
|
||||||
bottom: 32.0,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: child!,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
home: Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text('PopupMenu Test'),
|
|
||||||
actions: <Widget>[PopupMenuButton<int>(
|
|
||||||
placement: PopupMenuPlacement.belowButton,
|
|
||||||
child: SizedBox(
|
|
||||||
key: buttonKey,
|
|
||||||
height: height,
|
|
||||||
width: width,
|
|
||||||
child: const ColoredBox(
|
|
||||||
color: Colors.pink,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
itemBuilder: (BuildContext context) => <PopupMenuEntry<int>>[
|
|
||||||
PopupMenuItem<int>(
|
|
||||||
key: firstItemKey,
|
|
||||||
child: const Text('-1-'),
|
|
||||||
value: 1,
|
|
||||||
),
|
|
||||||
const PopupMenuItem<int>(child: Text('-2-'), value: 2,),
|
|
||||||
],
|
|
||||||
)],
|
|
||||||
),
|
|
||||||
body: Container(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await tester.pumpWidget(buildFrame(20.0, 20.0));
|
|
||||||
|
|
||||||
await tester.tap(find.byKey(buttonKey));
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
final Offset button = tester.getBottomRight(find.byKey(buttonKey));
|
|
||||||
final Offset popupMenu = tester.getTopRight(find.byKey(firstItemKey));
|
|
||||||
|
|
||||||
// The menu should popup below the button.
|
|
||||||
// The 8.0 pixels are [_kMenuScreenPadding] and [_kMenuVerticalPadding].
|
|
||||||
expect(popupMenu, Offset(button.dx - 8.0, button.dy + 8.0));
|
|
||||||
});
|
|
||||||
|
|
||||||
group('feedback', () {
|
group('feedback', () {
|
||||||
late FeedbackTester feedback;
|
late FeedbackTester feedback;
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ void main() {
|
|||||||
key: targetKey,
|
key: targetKey,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return PopupMenuButton<int>(
|
return PopupMenuButton<int>(
|
||||||
placement: PopupMenuPlacement.belowButton,
|
|
||||||
onSelected: (int value) {
|
onSelected: (int value) {
|
||||||
Navigator.pushNamed(context, '/next');
|
Navigator.pushNamed(context, '/next');
|
||||||
},
|
},
|
||||||
@ -79,20 +78,20 @@ void main() {
|
|||||||
Offset bottomLeft = tester.getBottomLeft(find.text('hello, world'));
|
Offset bottomLeft = tester.getBottomLeft(find.text('hello, world'));
|
||||||
Offset bottomRight = tester.getBottomRight(find.text('hello, world'));
|
Offset bottomRight = tester.getBottomRight(find.text('hello, world'));
|
||||||
|
|
||||||
expect(topLeft, const Offset(392.0, 347.5));
|
expect(topLeft, const Offset(392.0, 299.5));
|
||||||
expect(topRight, const Offset(596.0, 347.5));
|
expect(topRight, const Offset(596.0, 299.5));
|
||||||
expect(bottomLeft, const Offset(392.0, 364.5));
|
expect(bottomLeft, const Offset(392.0, 316.5));
|
||||||
expect(bottomRight, const Offset(596.0, 364.5));
|
expect(bottomRight, const Offset(596.0, 316.5));
|
||||||
|
|
||||||
topLeft = tester.getTopLeft(find.text('你好,世界'));
|
topLeft = tester.getTopLeft(find.text('你好,世界'));
|
||||||
topRight = tester.getTopRight(find.text('你好,世界'));
|
topRight = tester.getTopRight(find.text('你好,世界'));
|
||||||
bottomLeft = tester.getBottomLeft(find.text('你好,世界'));
|
bottomLeft = tester.getBottomLeft(find.text('你好,世界'));
|
||||||
bottomRight = tester.getBottomRight(find.text('你好,世界'));
|
bottomRight = tester.getBottomRight(find.text('你好,世界'));
|
||||||
|
|
||||||
expect(topLeft, const Offset(392.0, 395.5));
|
expect(topLeft, const Offset(392.0, 347.5));
|
||||||
expect(topRight, const Offset(477.0, 395.5));
|
expect(topRight, const Offset(477.0, 347.5));
|
||||||
expect(bottomLeft, const Offset(392.0, 412.5));
|
expect(bottomLeft, const Offset(392.0, 364.5));
|
||||||
expect(bottomRight, const Offset(477.0, 412.5));
|
expect(bottomRight, const Offset(477.0, 364.5));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Text baseline with EN locale', (WidgetTester tester) async {
|
testWidgets('Text baseline with EN locale', (WidgetTester tester) async {
|
||||||
@ -125,7 +124,6 @@ void main() {
|
|||||||
key: targetKey,
|
key: targetKey,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return PopupMenuButton<int>(
|
return PopupMenuButton<int>(
|
||||||
placement: PopupMenuPlacement.belowButton,
|
|
||||||
onSelected: (int value) {
|
onSelected: (int value) {
|
||||||
Navigator.pushNamed(context, '/next');
|
Navigator.pushNamed(context, '/next');
|
||||||
},
|
},
|
||||||
@ -166,19 +164,19 @@ void main() {
|
|||||||
Offset bottomLeft = tester.getBottomLeft(find.text('hello, world'));
|
Offset bottomLeft = tester.getBottomLeft(find.text('hello, world'));
|
||||||
Offset bottomRight = tester.getBottomRight(find.text('hello, world'));
|
Offset bottomRight = tester.getBottomRight(find.text('hello, world'));
|
||||||
|
|
||||||
expect(topLeft, const Offset(392.0, 348.0));
|
expect(topLeft, const Offset(392.0, 300.0));
|
||||||
expect(topRight, const Offset(584.0, 348.0));
|
expect(topRight, const Offset(584.0, 300.0));
|
||||||
expect(bottomLeft, const Offset(392.0, 364));
|
expect(bottomLeft, const Offset(392.0, 316));
|
||||||
expect(bottomRight, const Offset(584.0, 364));
|
expect(bottomRight, const Offset(584.0, 316));
|
||||||
|
|
||||||
topLeft = tester.getTopLeft(find.text('你好,世界'));
|
topLeft = tester.getTopLeft(find.text('你好,世界'));
|
||||||
topRight = tester.getTopRight(find.text('你好,世界'));
|
topRight = tester.getTopRight(find.text('你好,世界'));
|
||||||
bottomLeft = tester.getBottomLeft(find.text('你好,世界'));
|
bottomLeft = tester.getBottomLeft(find.text('你好,世界'));
|
||||||
bottomRight = tester.getBottomRight(find.text('你好,世界'));
|
bottomRight = tester.getBottomRight(find.text('你好,世界'));
|
||||||
|
|
||||||
expect(topLeft, const Offset(392.0, 396.0));
|
expect(topLeft, const Offset(392.0, 348.0));
|
||||||
expect(topRight, const Offset(472.0, 396.0));
|
expect(topRight, const Offset(472.0, 348.0));
|
||||||
expect(bottomLeft, const Offset(392.0, 412.0));
|
expect(bottomLeft, const Offset(392.0, 364.0));
|
||||||
expect(bottomRight, const Offset(472.0, 412.0));
|
expect(bottomRight, const Offset(472.0, 364.0));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user