Skip to content

Commit 6e85113

Browse files
authored
Add an example for SearchBar (#124992)
This PR is to: * Update API doc for `SearchBar`. * Add an example to show how to use a `SearchBar` as the builder of the `SearchAnchor`.
1 parent cc9ffd3 commit 6e85113

File tree

3 files changed

+132
-3
lines changed

3 files changed

+132
-3
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/material.dart';
6+
7+
/// Flutter code sample for [SearchBar].
8+
9+
void main() => runApp(const SearchBarApp());
10+
11+
class SearchBarApp extends StatefulWidget {
12+
const SearchBarApp({super.key});
13+
14+
@override
15+
State<SearchBarApp> createState() => _SearchBarAppState();
16+
}
17+
18+
class _SearchBarAppState extends State<SearchBarApp> {
19+
bool isDark = false;
20+
21+
@override
22+
Widget build(BuildContext context) {
23+
final ThemeData themeData = ThemeData(useMaterial3: true, brightness: isDark ? Brightness.dark : Brightness.light);
24+
25+
return MaterialApp(
26+
theme: themeData,
27+
home: Scaffold(
28+
appBar: AppBar(title: const Text('Search Bar Sample')),
29+
body: Padding(
30+
padding: const EdgeInsets.all(8.0),
31+
child: SearchAnchor(
32+
builder: (BuildContext context, SearchController controller) {
33+
return SearchBar(
34+
controller: controller,
35+
padding: const MaterialStatePropertyAll<EdgeInsets>(EdgeInsets.symmetric(horizontal: 16.0)),
36+
onTap: () { controller.openView(); },
37+
onChanged: (_) { controller.openView(); },
38+
leading: const Icon(Icons.search),
39+
trailing: <Widget>[
40+
Tooltip(
41+
message: 'Change brightness mode',
42+
child: IconButton(
43+
isSelected: isDark,
44+
onPressed: () {
45+
setState(() {
46+
isDark = !isDark;
47+
});
48+
},
49+
icon: const Icon(Icons.wb_sunny_outlined),
50+
selectedIcon: const Icon(Icons.brightness_2_outlined),
51+
),
52+
)
53+
],
54+
);
55+
},
56+
suggestionsBuilder: (BuildContext context, SearchController controller) {
57+
return List<ListTile>.generate(5, (int index) {
58+
final String item = 'item $index';
59+
return ListTile(
60+
title: Text(item),
61+
onTap: () {
62+
setState(() {
63+
controller.closeView(item);
64+
});
65+
},
66+
);
67+
});
68+
}),
69+
),
70+
),
71+
);
72+
}
73+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/material.dart';
6+
import 'package:flutter_api_samples/material/search_anchor/search_bar.0.dart' as example;
7+
import 'package:flutter_test/flutter_test.dart';
8+
9+
void main() {
10+
testWidgets('Can open search view', (WidgetTester tester) async {
11+
await tester.pumpWidget(
12+
const example.SearchBarApp(),
13+
);
14+
15+
final Finder searchBarFinder = find.byType(SearchBar);
16+
final SearchBar searchBar = tester.widget<SearchBar>(searchBarFinder);
17+
expect(find.byIcon(Icons.search), findsOneWidget);
18+
expect(searchBar.trailing, isNotEmpty);
19+
expect(searchBar.trailing?.length, equals(1));
20+
final Finder trailingButtonFinder = find.widgetWithIcon(IconButton, Icons.wb_sunny_outlined);
21+
expect(trailingButtonFinder, findsOneWidget);
22+
23+
await tester.tap(trailingButtonFinder);
24+
await tester.pumpAndSettle();
25+
26+
expect(find.widgetWithIcon(IconButton, Icons.brightness_2_outlined), findsOneWidget);
27+
28+
await tester.tap(searchBarFinder);
29+
await tester.pumpAndSettle();
30+
31+
expect(find.text('item 0'), findsOneWidget);
32+
expect(find.text('item 1'), findsOneWidget);
33+
expect(find.text('item 2'), findsOneWidget);
34+
expect(find.text('item 3'), findsOneWidget);
35+
expect(find.text('item 4'), findsOneWidget);
36+
});
37+
}

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -970,9 +970,13 @@ class SearchController extends TextEditingController {
970970

971971
/// A Material Design search bar.
972972
///
973-
/// Search bars include a [leading] Search icon, a text input field and optional
974-
/// [trailing] icons. A search bar is typically used to open a search view.
975-
/// It is the default trigger for a search view.
973+
/// A [SearchBar] looks like a [TextField]. Tapping a SearchBar typically shows a
974+
/// "search view" route: a route with the search bar at the top and a list of
975+
/// suggested completions for the search bar's text below. [SearchBar]s are
976+
/// usually created by a [SearchAnchor.builder]. The builder provides a
977+
/// [SearchController] that's used by the search bar's [SearchBar.onTap] or
978+
/// [SearchBar.onChanged] callbacks to show the search view and to hide it
979+
/// when the user selects a suggestion.
976980
///
977981
/// For [TextDirection.ltr], the [leading] widget is on the left side of the bar.
978982
/// It should contain either a navigational action (such as a menu or up-arrow)
@@ -982,6 +986,21 @@ class SearchController extends TextEditingController {
982986
/// the search bar. Typically only one or two action icons are included.
983987
/// These actions can represent additional modes of searching (like voice search),
984988
/// a separate high-level action (such as current location) or an overflow menu.
989+
///
990+
/// {@tool dartpad}
991+
/// This example demonstrates how to use a [SearchBar] as the return value of the
992+
/// [SearchAnchor.builder] property. The [SearchBar] also includes a leading search
993+
/// icon and a trailing action to toggle the brightness.
994+
///
995+
/// ** See code in examples/api/lib/material/search_anchor/search_bar.0.dart **
996+
/// {@end-tool}
997+
///
998+
/// See also:
999+
///
1000+
/// * [SearchAnchor], a widget that typically uses an [IconButton] or a [SearchBar]
1001+
/// to manage a "search view" route.
1002+
/// * [SearchBarTheme], a widget that overrides the default configuration of a search bar.
1003+
/// * [SearchViewTheme], a widget that overrides the default configuration of a search view.
9851004
class SearchBar extends StatefulWidget {
9861005
/// Creates a Material Design search bar.
9871006
const SearchBar({

0 commit comments

Comments
 (0)