Add optional param to useRootNavigator when showSearch (#84581)

* Add optional param to useRootNavigator when showSearch

* Add test showSearch with rootNavigator

* fix analyze

* Change default value useRootNavigator to true
This commit is contained in:
tbm98 2021-06-17 23:16:15 +07:00 committed by GitHub
parent 6644d548e9
commit a65328b460
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 1 deletions

View file

@ -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 `true` and the search page
/// route created by this method is pushed to the furthest 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 = true,
}) {
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,
));
}

View file

@ -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);
},
child: const Text('showSearchRootNavigator')),
TextButton(
onPressed: () async {
await showSearch(context: context, delegate: delegate, useRootNavigator: false);
},
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++;
}
}