Unverified Commit 70bb5d1d authored by rami-a's avatar rami-a Committed by GitHub

Add flag to use root navigator for showModalBottomSheet (#35878)

* Add flag to use root navigator for showModalBottomSheet

* Add documentation

* Add tests

* Address feedback and fix analyzer issues

* Address feedback

* Update comments
parent 14e4565f
......@@ -400,6 +400,11 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
/// a [GridView] and have the bottom sheet be draggable, you should set this
/// parameter to true.
///
/// The `useRootNavigator` parameter ensures that the root navigator is used to
/// display the [BottomSheet] when set to `true`. This is useful in the case
/// that a modal [BottomSheet] needs to be displayed above all other content
/// but the caller is inside another [Navigator].
///
/// Returns a `Future` that resolves to the value (if any) that was passed to
/// [Navigator.pop] when the modal bottom sheet was closed.
///
......@@ -417,14 +422,16 @@ Future<T> showModalBottomSheet<T>({
double elevation,
ShapeBorder shape,
bool isScrollControlled = false,
bool useRootNavigator = false,
}) {
assert(context != null);
assert(builder != null);
assert(isScrollControlled != null);
assert(useRootNavigator != null);
assert(debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context));
return Navigator.push(context, _ModalBottomSheetRoute<T>(
return Navigator.of(context, rootNavigator: useRootNavigator).push(_ModalBottomSheetRoute<T>(
builder: builder,
theme: Theme.of(context, shadowThemeOnly: true),
isScrollControlled: isScrollControlled,
......
......@@ -361,4 +361,91 @@ void main() {
), ignoreTransform: true, ignoreRect: true, ignoreId: true));
semantics.dispose();
});
testWidgets('showModalBottomSheet does not use root Navigator by default', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Navigator(onGenerateRoute: (RouteSettings settings) => MaterialPageRoute<void>(builder: (_) {
return const _TestPage();
})),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.ac_unit),
title: Text('Item 1'),
),
BottomNavigationBarItem(
icon: Icon(Icons.style),
title: Text('Item 2'),
)
],
),
),
));
await tester.tap(find.text('Show bottom sheet'));
await tester.pumpAndSettle();
// Bottom sheet is displayed in correct position within the inner navigator
// and above the BottomNavigationBar.
expect(tester.getBottomLeft(find.byType(BottomSheet)).dy, 544.0);
});
testWidgets('showModalBottomSheet uses root Navigator when specified', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Navigator(onGenerateRoute: (RouteSettings settings) => MaterialPageRoute<void>(builder: (_) {
return const _TestPage(useRootNavigator: true);
})),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.ac_unit),
title: Text('Item 1'),
),
BottomNavigationBarItem(
icon: Icon(Icons.style),
title: Text('Item 2'),
)
],
),
),
));
await tester.tap(find.text('Show bottom sheet'));
await tester.pumpAndSettle();
// Bottom sheet is displayed in correct position above all content including
// the BottomNavigationBar.
expect(tester.getBottomLeft(find.byType(BottomSheet)).dy, 600.0);
});
}
class _TestPage extends StatelessWidget {
const _TestPage({Key key, this.useRootNavigator}) : super(key: key);
final bool useRootNavigator;
@override
Widget build(BuildContext context) {
return Center(
child: FlatButton(
child: const Text('Show bottom sheet'),
onPressed: () {
if (useRootNavigator != null) {
showModalBottomSheet<void>(
useRootNavigator: useRootNavigator,
context: context,
builder: (_) => const Text('Modal bottom sheet'),
);
} else {
showModalBottomSheet<void>(
context: context,
builder: (_) => const Text('Modal bottom sheet'),
);
}
}
),
);
}
}
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