@@ -9,23 +9,36 @@ typedef QueryBuilder<T> = List<T> Function(
99
1010class GFSearchBar <T > extends StatefulWidget {
1111 const GFSearchBar ({
12- @required this .dataList ,
13- @required this .popupListItemBuilder ,
14- @required this .queryBuilder ,
12+ @required this .searchList ,
13+ @required this .overlaySearchListItemBuilder ,
14+ @required this .searchQueryBuilder ,
1515 Key key,
1616 this .onItemSelected,
1717 this .hideSearchBoxWhenItemSelected = false ,
18- this .listContainerHeight ,
18+ this .overlaySearchListHeight ,
1919 this .noItemsFoundWidget,
2020 }) : super (key: key);
2121
22- final List <T > dataList;
23- final QueryListItemBuilder <T > popupListItemBuilder;
22+
23+ /// List of [text] or [widget] reference for users
24+ final List <T > searchList;
25+
26+ /// defines how the [searchList] items look like in overlayContainer
27+ final QueryListItemBuilder <T > overlaySearchListItemBuilder;
28+
29+ /// if true, it will hide the [searchBox]
2430 final bool hideSearchBoxWhenItemSelected;
25- final double listContainerHeight;
26- final QueryBuilder <T > queryBuilder;
31+
32+ /// defines the height of [searchList] overlay container
33+ final double overlaySearchListHeight;
34+
35+ /// can search and filter the [searchList]
36+ final QueryBuilder <T > searchQueryBuilder;
37+
38+ /// displays the [widget] when the search item failed
2739 final Widget noItemsFoundWidget;
2840
41+ /// defines what to do with onSelect [SearchList] item
2942 final OnItemSelected <T > onItemSelected;
3043
3144 @override
@@ -35,15 +48,15 @@ class GFSearchBar<T> extends StatefulWidget {
3548class MySingleChoiceSearchState <T > extends State <GFSearchBar <T >> {
3649 final _controller = TextEditingController ();
3750 List <T > _list;
38- List <T > _tempList ;
51+ List <T > _searchList ;
3952 bool isFocused;
4053 FocusNode _focusNode;
4154 ValueNotifier <T > notifier;
4255 bool isRequiredCheckFailed;
43- Widget textField ;
44- OverlayEntry overlayEntry ;
56+ Widget searchBox ;
57+ OverlayEntry overlaySearchList ;
4558 bool showTextBox = false ;
46- double listContainerHeight ;
59+ double overlaySearchListHeight ;
4760 final LayerLink _layerLink = LayerLink ();
4861 final double textBoxHeight = 48 ;
4962 final TextEditingController textController = TextEditingController ();
@@ -55,62 +68,62 @@ class MySingleChoiceSearchState<T> extends State<GFSearchBar<T>> {
5568 }
5669
5770 void init () {
58- _tempList = < T > [];
71+ _searchList = < T > [];
5972 notifier = ValueNotifier (null );
6073 _focusNode = FocusNode ();
6174 isFocused = false ;
62- _list = List <T >.from (widget.dataList );
63- _tempList .addAll (_list);
75+ _list = List <T >.from (widget.searchList );
76+ _searchList .addAll (_list);
6477 _focusNode.addListener (() {
6578 if (! _focusNode.hasFocus) {
6679 _controller.clear ();
67- if (overlayEntry != null ) {
68- overlayEntry .remove ();
80+ if (overlaySearchList != null ) {
81+ overlaySearchList .remove ();
6982 }
70- overlayEntry = null ;
83+ overlaySearchList = null ;
7184 } else {
72- _tempList
85+ _searchList
7386 ..clear ()
7487 ..addAll (_list);
75- if (overlayEntry == null ) {
76- onTextfieldFocus ();
88+ if (overlaySearchList == null ) {
89+ onTextFieldFocus ();
7790 } else {
78- overlayEntry .markNeedsBuild ();
91+ overlaySearchList .markNeedsBuild ();
7992 }
8093 }
8194 });
8295 _controller.addListener (() {
8396 final text = _controller.text;
8497 if (text.trim ().isNotEmpty) {
85- _tempList .clear ();
86- final filterList = widget.queryBuilder (text, widget.dataList );
98+ _searchList .clear ();
99+ final filterList = widget.searchQueryBuilder (text, widget.searchList );
87100 if (filterList == null ) {
88101 throw Exception (
89102 "List cannot be null" ,
90103 );
91104 }
92- _tempList .addAll (filterList);
93- if (overlayEntry == null ) {
94- onTextfieldFocus ();
105+ _searchList .addAll (filterList);
106+ if (overlaySearchList == null ) {
107+ onTextFieldFocus ();
95108 } else {
96- overlayEntry .markNeedsBuild ();
109+ overlaySearchList .markNeedsBuild ();
97110 }
98111 } else {
99- _tempList
112+ _searchList
100113 ..clear ()
101114 ..addAll (_list);
102- if (overlayEntry == null ) {
103- onTextfieldFocus ();
115+ if (overlaySearchList == null ) {
116+ onTextFieldFocus ();
104117 } else {
105- overlayEntry .markNeedsBuild ();
118+ overlaySearchList .markNeedsBuild ();
106119 }
107120 }
108121 });
109122 }
110123
111124 @override
112125 void didUpdateWidget (GFSearchBar oldWidget) {
113- if (oldWidget.dataList != widget.dataList ) {
126+ if (oldWidget.searchList != widget.searchList ) {
114127 init ();
115128 }
116129 super .didUpdateWidget (oldWidget);
@@ -119,9 +132,9 @@ class MySingleChoiceSearchState<T> extends State<GFSearchBar<T>> {
119132 @override
120133 Widget build (BuildContext context) {
121134
122- listContainerHeight =
123- widget.listContainerHeight ?? MediaQuery .of (context).size.height / 4 ;
124- textField = Padding (
135+ overlaySearchListHeight =
136+ widget.overlaySearchListHeight ?? MediaQuery .of (context).size.height / 4 ;
137+ searchBox = Padding (
125138 padding: const EdgeInsets .symmetric (vertical: 12 , horizontal: 16 ),
126139 child: TextField (
127140 controller: _controller,
@@ -160,18 +173,18 @@ class MySingleChoiceSearchState<T> extends State<GFSearchBar<T>> {
160173 else
161174 CompositedTransformTarget (
162175 link: _layerLink,
163- child: textField ,
176+ child: searchBox ,
164177 ),
165178 ],
166179 );
167180 return column;
168181 }
169182
170- void onDropDownItemSelected (T item) {
171- if (overlayEntry != null ) {
172- overlayEntry .remove ();
183+ void onSearchListItemSelected (T item) {
184+ if (overlaySearchList != null ) {
185+ overlaySearchList .remove ();
173186 }
174- overlayEntry = null ;
187+ overlaySearchList = null ;
175188 _controller.clear ();
176189 _focusNode.unfocus ();
177190 setState (() {
@@ -184,24 +197,24 @@ class MySingleChoiceSearchState<T> extends State<GFSearchBar<T>> {
184197 }
185198 }
186199
187- void onTextfieldFocus () {
188- final RenderBox textFieldRenderBox = context.findRenderObject ();
200+ void onTextFieldFocus () {
201+ final RenderBox searchBoxRenderBox = context.findRenderObject ();
189202 final RenderBox overlay = Overlay .of (context).context.findRenderObject ();
190- final width = textFieldRenderBox .size.width;
203+ final width = searchBoxRenderBox .size.width;
191204 final position = RelativeRect .fromRect (
192205 Rect .fromPoints (
193- textFieldRenderBox .localToGlobal (
194- textFieldRenderBox .size.topLeft (Offset .zero),
206+ searchBoxRenderBox .localToGlobal (
207+ searchBoxRenderBox .size.topLeft (Offset .zero),
195208 ancestor: overlay,
196209 ),
197- textFieldRenderBox .localToGlobal (
198- textFieldRenderBox .size.topRight (Offset .zero),
210+ searchBoxRenderBox .localToGlobal (
211+ searchBoxRenderBox .size.topRight (Offset .zero),
199212 ancestor: overlay,
200213 ),
201214 ),
202215 Offset .zero & overlay.size,
203216 );
204- overlayEntry = OverlayEntry (
217+ overlaySearchList = OverlayEntry (
205218 builder: (context) {
206219 final height = MediaQuery .of (context).size.height;
207220 return Positioned (
@@ -210,22 +223,22 @@ class MySingleChoiceSearchState<T> extends State<GFSearchBar<T>> {
210223 child: CompositedTransformFollower (
211224 offset: Offset (
212225 0 ,
213- height - position.bottom < listContainerHeight
226+ height - position.bottom < overlaySearchListHeight
214227 ? (textBoxHeight + 6.0 )
215- : - (listContainerHeight - 8.0 ),
228+ : - (overlaySearchListHeight - 8.0 ),
216229 ),
217230 showWhenUnlinked: false ,
218231 link: _layerLink,
219232 child: Container (
220- height: listContainerHeight ,
233+ height: overlaySearchListHeight ,
221234 margin: const EdgeInsets .symmetric (horizontal: 12 ),
222235 child: Card (
223236 color: Colors .white,
224237 elevation: 5 ,
225238 shape: const RoundedRectangleBorder (
226239 borderRadius: BorderRadius .all (Radius .circular (4 )),
227240 ),
228- child: _tempList .isNotEmpty
241+ child: _searchList .isNotEmpty
229242 ? Scrollbar (
230243 child: ListView .separated (
231244 padding: const EdgeInsets .symmetric (vertical: 4 ),
@@ -235,13 +248,13 @@ class MySingleChoiceSearchState<T> extends State<GFSearchBar<T>> {
235248 itemBuilder: (context, index) => Material (
236249 color: Colors .transparent,
237250 child: InkWell (
238- onTap: () => onDropDownItemSelected (_tempList [index]),
239- child: widget.popupListItemBuilder (
240- _tempList .elementAt (index),
251+ onTap: () => onSearchListItemSelected (_searchList [index]),
252+ child: widget.overlaySearchListItemBuilder (
253+ _searchList .elementAt (index),
241254 ),
242255 ),
243256 ),
244- itemCount: _tempList .length,
257+ itemCount: _searchList .length,
245258 ),
246259 )
247260 : widget.noItemsFoundWidget != null
@@ -257,7 +270,7 @@ class MySingleChoiceSearchState<T> extends State<GFSearchBar<T>> {
257270 );
258271 },
259272 );
260- Overlay .of (context).insert (overlayEntry );
273+ Overlay .of (context).insert (overlaySearchList );
261274 }
262275}
263276
0 commit comments