Unverified Commit ddc6c343 authored by tbm98's avatar tbm98 Committed by GitHub

Reland: Add optional param to useRootNavigator when showSearch (#84872)

parent 03b76194
......@@ -35,6 +35,12 @@ import 'theme.dart';
/// call. Call [SearchDelegate.close] before re-using the same delegate instance
/// for another [showSearch] call.
///
/// The `useRootNavigator` argument is used to determine whether to push the
/// search page to the [Navigator] furthest from or nearest to the given
/// `context`. By default, `useRootNavigator` is `false` and the search page
/// route created by this method is pushed to the nearest navigator to the
/// given `context`. It can not be `null`.
///
/// The transition to the search page triggered by this method looks best if the
/// screen triggering the transition contains an [AppBar] at the top and the
/// transition is called from an [IconButton] that's part of [AppBar.actions].
......@@ -54,12 +60,14 @@ Future<T?> showSearch<T>({
required BuildContext context,
required SearchDelegate<T> delegate,
String? query = '',
bool useRootNavigator = false,
}) {
assert(delegate != null);
assert(context != null);
assert(useRootNavigator != null);
delegate.query = query ?? delegate.query;
delegate._currentBody = _SearchBody.suggestions;
return Navigator.of(context).push(_SearchPageRoute<T>(
return Navigator.of(context, rootNavigator: useRootNavigator).push(_SearchPageRoute<T>(
delegate: delegate,
));
}
......
......@@ -841,6 +841,66 @@ void main() {
expect(find.text('Suggestions'), findsNothing);
expect(selectedResults, <String>['Result']);
});
testWidgets('showSearch with useRootNavigator', (WidgetTester tester) async {
final _MyNavigatorObserver rootObserver = _MyNavigatorObserver();
final _MyNavigatorObserver localObserver = _MyNavigatorObserver();
final _TestEmptySearchDelegate delegate = _TestEmptySearchDelegate(
result: 'Result',
suggestions: 'Suggestions',
);
await tester.pumpWidget(MaterialApp(
navigatorObservers: <NavigatorObserver>[rootObserver],
home: Navigator(
observers: <NavigatorObserver>[localObserver],
onGenerateRoute: (RouteSettings settings) {
if (settings.name == 'nested') {
return MaterialPageRoute<dynamic>(
builder: (BuildContext context) => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
onPressed: () async {
await showSearch(context: context, delegate: delegate, useRootNavigator: true);
},
child: const Text('showSearchRootNavigator')),
TextButton(
onPressed: () async {
await showSearch(context: context, delegate: delegate);
},
child: const Text('showSearchLocalNavigator')),
],
),
settings: settings,
);
}
throw UnimplementedError();
},
initialRoute: 'nested',
),
));
expect(rootObserver.pushCount, 0);
expect(localObserver.pushCount, 0);
// showSearch normal and back
await tester.tap(find.text('showSearchLocalNavigator'));
await tester.pumpAndSettle();
await tester.tap(find.byTooltip('Close'));
await tester.pumpAndSettle();
expect(rootObserver.pushCount, 0);
expect(localObserver.pushCount, 1);
// showSearch with rootNavigator
await tester.tap(find.text('showSearchRootNavigator'));
await tester.pumpAndSettle();
await tester.tap(find.byTooltip('Close'));
await tester.pumpAndSettle();
expect(rootObserver.pushCount, 1);
expect(localObserver.pushCount, 1);
});
}
class TestHomePage extends StatelessWidget {
......@@ -1026,3 +1086,16 @@ class _TestEmptySearchDelegate extends SearchDelegate<String> {
);
}
}
class _MyNavigatorObserver extends NavigatorObserver {
int pushCount = 0;
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
// don't count the root route
if (<String>['nested', '/'].contains(route.settings.name)) {
return;
}
pushCount++;
}
}
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