Skip to content

Commit 6f98b48

Browse files
authored
fix: add parameter to maintainState of SearchDelegate (#152444)
Add parameter to `showSearch`, which is passed to `_SearchPageRoute` to maintain the state of the SearchDelegate. - fix #43582 _Just contributed this change to start the conversation on how the #43582 can be addressed. Have not added tests yet._
1 parent a9b2d8d commit 6f98b48

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

packages/flutter/lib/src/material/search.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ import 'theme.dart';
4848
/// route created by this method is pushed to the nearest navigator to the
4949
/// given `context`. It can not be `null`.
5050
///
51+
/// The `maintainState` argument is used to determine if the route should remain
52+
/// in memory when it is inactive (see [ModalRoute.maintainState] for more details].
53+
/// By default, `maintainState` is `false`.
54+
///
5155
/// The transition to the search page triggered by this method looks best if the
5256
/// screen triggering the transition contains an [AppBar] at the top and the
5357
/// transition is called from an [IconButton] that's part of [AppBar.actions].
@@ -68,11 +72,13 @@ Future<T?> showSearch<T>({
6872
required SearchDelegate<T> delegate,
6973
String? query = '',
7074
bool useRootNavigator = false,
75+
bool maintainState = false,
7176
}) {
7277
delegate.query = query ?? delegate.query;
7378
delegate._currentBody = _SearchBody.suggestions;
7479
return Navigator.of(context, rootNavigator: useRootNavigator).push(_SearchPageRoute<T>(
7580
delegate: delegate,
81+
maintainState: maintainState
7682
));
7783
}
7884

@@ -417,6 +423,7 @@ enum _SearchBody {
417423
class _SearchPageRoute<T> extends PageRoute<T> {
418424
_SearchPageRoute({
419425
required this.delegate,
426+
required this.maintainState,
420427
}) {
421428
assert(
422429
delegate._route == null,
@@ -429,6 +436,9 @@ class _SearchPageRoute<T> extends PageRoute<T> {
429436

430437
final SearchDelegate<T> delegate;
431438

439+
@override
440+
final bool maintainState;
441+
432442
@override
433443
Color? get barrierColor => null;
434444

@@ -438,9 +448,6 @@ class _SearchPageRoute<T> extends PageRoute<T> {
438448
@override
439449
Duration get transitionDuration => const Duration(milliseconds: 300);
440450

441-
@override
442-
bool get maintainState => false;
443-
444451
@override
445452
Widget buildTransitions(
446453
BuildContext context,

packages/flutter/test/material/search_test.dart

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,63 @@ void main() {
11751175
await tester.pump();
11761176
expect(textField.controller!.text.length, 15);
11771177
}, skip: kIsWeb); // [intended] We do not use Flutter-rendered context menu on the Web.
1178+
1179+
testWidgets('showSearch with maintainState on the route', (WidgetTester tester) async {
1180+
final _MyNavigatorObserver navigationObserver = _MyNavigatorObserver();
1181+
1182+
final _TestEmptySearchDelegate delegate = _TestEmptySearchDelegate();
1183+
addTearDown(delegate.dispose);
1184+
1185+
await tester.pumpWidget(MaterialApp(
1186+
navigatorObservers: <NavigatorObserver>[navigationObserver],
1187+
home: Builder(builder: (BuildContext context) => Column(
1188+
mainAxisAlignment: MainAxisAlignment.center,
1189+
children: <Widget>[
1190+
TextButton(
1191+
onPressed: () async {
1192+
await showSearch(
1193+
context: context,
1194+
delegate: delegate,
1195+
);
1196+
},
1197+
child: const Text('showSearch'),
1198+
),
1199+
TextButton(
1200+
onPressed: () async {
1201+
await showSearch(
1202+
context: context,
1203+
delegate: delegate,
1204+
maintainState: true,
1205+
);
1206+
},
1207+
child: const Text('showSearchWithMaintainState'),
1208+
),
1209+
],
1210+
)),
1211+
));
1212+
1213+
expect(navigationObserver.pushCount, 0);
1214+
expect(navigationObserver.maintainState, false);
1215+
1216+
// showSearch normal and back.
1217+
await tester.tap(find.text('showSearch'));
1218+
await tester.pumpAndSettle();
1219+
final Finder backButtonFinder = find.byType(BackButton);
1220+
expect(backButtonFinder, findsWidgets);
1221+
await tester.tap(find.byTooltip('Close'));
1222+
await tester.pumpAndSettle();
1223+
expect(navigationObserver.pushCount, 1);
1224+
expect(navigationObserver.maintainState, false);
1225+
1226+
// showSearch with maintainState.
1227+
await tester.tap(find.text('showSearchWithMaintainState'));
1228+
await tester.pumpAndSettle();
1229+
expect(backButtonFinder, findsWidgets);
1230+
await tester.tap(find.byTooltip('Close'));
1231+
await tester.pumpAndSettle();
1232+
expect(navigationObserver.pushCount, 2);
1233+
expect(navigationObserver.maintainState, true);
1234+
});
11781235
}
11791236

11801237
class TestHomePage extends StatelessWidget {
@@ -1358,6 +1415,7 @@ class _TestEmptySearchDelegate extends SearchDelegate<String> {
13581415
}
13591416

13601417
class _MyNavigatorObserver extends NavigatorObserver {
1418+
bool maintainState = false;
13611419
int pushCount = 0;
13621420

13631421
@override
@@ -1366,6 +1424,9 @@ class _MyNavigatorObserver extends NavigatorObserver {
13661424
if (<String>['nested', '/'].contains(route.settings.name)) {
13671425
return;
13681426
}
1427+
if (route is PageRoute) {
1428+
maintainState = route.maintainState;
1429+
}
13691430
pushCount++;
13701431
}
13711432
}

0 commit comments

Comments
 (0)