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
5import 'package:flutter/material.dart';
6
7/// Flutter code sample for [SearchAnchor.bar].
8
9void main() => runApp(const SearchBarApp());
10
11class SearchBarApp extends StatefulWidget {
12 const SearchBarApp({super.key});
13
14 @override
15 State<SearchBarApp> createState() => _SearchBarAppState();
16}
17
18class _SearchBarAppState extends State<SearchBarApp> {
19 Color? selectedColorSeed;
20 List<ColorLabel> searchHistory = <ColorLabel>[];
21
22 Iterable<Widget> getHistoryList(SearchController controller) {
23 return searchHistory.map(
24 (ColorLabel color) => ListTile(
25 leading: const Icon(Icons.history),
26 title: Text(color.label),
27 trailing: IconButton(
28 icon: const Icon(Icons.call_missed),
29 onPressed: () {
30 controller.text = color.label;
31 controller.selection = TextSelection.collapsed(offset: controller.text.length);
32 },
33 ),
34 ),
35 );
36 }
37
38 Iterable<Widget> getSuggestions(SearchController controller) {
39 final String input = controller.value.text;
40 return ColorLabel.values
41 .where((ColorLabel color) => color.label.contains(input))
42 .map(
43 (ColorLabel filteredColor) => ListTile(
44 leading: CircleAvatar(backgroundColor: filteredColor.color),
45 title: Text(filteredColor.label),
46 trailing: IconButton(
47 icon: const Icon(Icons.call_missed),
48 onPressed: () {
49 controller.text = filteredColor.label;
50 controller.selection = TextSelection.collapsed(offset: controller.text.length);
51 },
52 ),
53 onTap: () {
54 controller.closeView(filteredColor.label);
55 handleSelection(filteredColor);
56 },
57 ),
58 );
59 }
60
61 void handleSelection(ColorLabel selectedColor) {
62 setState(() {
63 selectedColorSeed = selectedColor.color;
64 if (searchHistory.length >= 5) {
65 searchHistory.removeLast();
66 }
67 searchHistory.insert(0, selectedColor);
68 });
69 }
70
71 @override
72 Widget build(BuildContext context) {
73 final ThemeData themeData = ThemeData(colorSchemeSeed: selectedColorSeed);
74 final ColorScheme colors = themeData.colorScheme;
75
76 return MaterialApp(
77 theme: themeData,
78 home: Scaffold(
79 appBar: AppBar(title: const Text('Search Bar Sample')),
80 body: Align(
81 alignment: Alignment.topCenter,
82 child: Column(
83 children: <Widget>[
84 SearchAnchor.bar(
85 barHintText: 'Search colors',
86 suggestionsBuilder: (BuildContext context, SearchController controller) {
87 if (controller.text.isEmpty) {
88 if (searchHistory.isNotEmpty) {
89 return getHistoryList(controller);
90 }
91 return <Widget>[
92 Center(
93 child: Text('No search history.', style: TextStyle(color: colors.outline)),
94 ),
95 ];
96 }
97 return getSuggestions(controller);
98 },
99 ),
100 cardSize,
101 Card(color: colors.primary, child: cardSize),
102 Card(color: colors.onPrimary, child: cardSize),
103 Card(color: colors.primaryContainer, child: cardSize),
104 Card(color: colors.onPrimaryContainer, child: cardSize),
105 Card(color: colors.secondary, child: cardSize),
106 Card(color: colors.onSecondary, child: cardSize),
107 ],
108 ),
109 ),
110 ),
111 );
112 }
113}
114
115SizedBox cardSize = const SizedBox(width: 80, height: 30);
116
117enum ColorLabel {
118 red('red', Colors.red),
119 orange('orange', Colors.orange),
120 yellow('yellow', Colors.yellow),
121 green('green', Colors.green),
122 blue('blue', Colors.blue),
123 indigo('indigo', Colors.indigo),
124 violet('violet', Color(0xFF8F00FF)),
125 purple('purple', Colors.purple),
126 pink('pink', Colors.pink),
127 silver('silver', Color(0xFF808080)),
128 gold('gold', Color(0xFFFFD700)),
129 beige('beige', Color(0xFFF5F5DC)),
130 brown('brown', Colors.brown),
131 grey('grey', Colors.grey),
132 black('black', Colors.black),
133 white('white', Colors.white);
134
135 const ColorLabel(this.label, this.color);
136 final String label;
137 final Color color;
138}
139