@@ -37,6 +37,7 @@ class SearchAnchorControl extends StatefulWidget {
3737class _SearchAnchorControlState extends State <SearchAnchorControl > {
3838 late final SearchController _controller;
3939 bool _focused = false ;
40+ TextCapitalization _textCapitalization = TextCapitalization .none;
4041 late final FocusNode _focusNode;
4142 String ? _lastFocusValue;
4243 String ? _lastBlurValue;
@@ -68,15 +69,54 @@ class _SearchAnchorControlState extends State<SearchAnchorControl> {
6869 }
6970
7071 void _searchTextChanged () {
71- debugPrint ("_searchTextChanged: ${_controller .text }" );
72+ _textCapitalization = parseTextCapitalization (
73+ widget.control.attrString ("capitalization" ), TextCapitalization .none)! ;
7274 _updateValue (_controller.text);
7375 }
7476
7577 void _updateValue (String value) {
76- debugPrint ("SearchBar.changeValue: $value " );
78+ value = applyCapitalization (value);
79+ if (_controller.value.text != value) {
80+ _controller.value = TextEditingValue (
81+ text: value,
82+ selection: TextSelection .collapsed (offset: value.length),
83+ );
84+ }
85+
7786 widget.backend.updateControlState (widget.control.id, {"value" : value});
7887 }
7988
89+ String applyCapitalization (String text) {
90+ switch (_textCapitalization) {
91+ /// Capitalizes the first character of each word.
92+ case TextCapitalization .words:
93+ return text
94+ .split (RegExp (r'\s+' ))
95+ .map ((word) => word.isNotEmpty
96+ ? word[0 ].toUpperCase () + word.substring (1 ).toLowerCase ()
97+ : word)
98+ .join (' ' );
99+
100+ /// Capitalizes the first character of each sentence.
101+ case TextCapitalization .sentences:
102+ return text
103+ .split ('. ' )
104+ .map ((sentence) => sentence.isNotEmpty
105+ ? sentence.trimLeft ()[0 ].toUpperCase () +
106+ sentence.substring (1 ).toLowerCase ()
107+ : sentence)
108+ .join ('. ' );
109+
110+ /// Capitalizes all characters.
111+ case TextCapitalization .characters:
112+ return text.toUpperCase ();
113+
114+ /// No change.
115+ case TextCapitalization .none:
116+ return text;
117+ }
118+ }
119+
80120 @override
81121 Widget build (BuildContext context) {
82122 debugPrint ("SearchAnchor build: ${widget .control .id }" );
@@ -103,9 +143,6 @@ class _SearchAnchorControlState extends State<SearchAnchorControl> {
103143 widget.children.where ((c) => c.name == "viewLeading" && c.isVisible);
104144 var viewTrailingCtrls =
105145 widget.children.where ((c) => c.name == "viewTrailing" && c.isVisible);
106-
107- var textCapitalization = parseTextCapitalization (
108- widget.control.attrString ("textCapitalization" ));
109146 TextInputType keyboardType = parseTextInputType (
110147 widget.control.attrString ("keyboardType" ), TextInputType .text)! ;
111148
@@ -197,13 +234,13 @@ class _SearchAnchorControlState extends State<SearchAnchorControl> {
197234 : null ,
198235 viewSurfaceTintColor:
199236 widget.control.attrColor ("viewSurfaceTintColor" , context),
200- textCapitalization: textCapitalization ,
237+ textCapitalization: _textCapitalization ,
201238 keyboardType: keyboardType,
202239 builder: (BuildContext context, SearchController controller) {
203240 return SearchBar (
204241 controller: controller,
205242 keyboardType: keyboardType,
206- textCapitalization: textCapitalization ,
243+ textCapitalization: _textCapitalization ,
207244 autoFocus: widget.control.attrBool ("autoFocus" , false )! ,
208245 focusNode: _focusNode,
209246 hintText: widget.control.attrString ("barHintText" ),
0 commit comments