@@ -556,6 +556,13 @@ typedef ClearSearchField = Function(
556
556
bool force,
557
557
});
558
558
559
+ /// Provided by clients to specify where the autocomplete overlay should be
560
+ /// positioned relative to the input text.
561
+ typedef OverlayXPositionBuilder = double Function (
562
+ String inputValue,
563
+ TextStyle inputStyle,
564
+ );
565
+
559
566
mixin SearchFieldMixin <T extends StatefulWidget > on State <T > {
560
567
TextEditingController searchTextFieldController;
561
568
FocusNode _searchFieldFocusNode;
@@ -601,9 +608,10 @@ mixin SearchFieldMixin<T extends StatefulWidget> on State<T> {
601
608
/// [searchFieldKey]
602
609
/// [searchFieldEnabled]
603
610
/// [onSelection]
604
- /// [onHilightDropdown ] use to override default highlghter.
611
+ /// [onHighlightDropdown ] use to override default highlghter.
605
612
/// [decoration]
606
- /// [tracking] if true displays pop-up to the right of the TextField's caret.
613
+ /// [overlayXPositionBuilder] callback function to determine where the
614
+ /// autocomplete overlay should be positioned relative to the input text.
607
615
/// [supportClearField] if true clear TextField content if pop-up not visible. If
608
616
/// pop-up is visible close the pop-up on first ESCAPE.
609
617
/// [keyEventsToPropogate] a set of key events that should be propogated to
@@ -617,7 +625,7 @@ mixin SearchFieldMixin<T extends StatefulWidget> on State<T> {
617
625
HighlightAutoComplete onHighlightDropdown,
618
626
InputDecoration decoration,
619
627
String label,
620
- bool tracking = false ,
628
+ OverlayXPositionBuilder overlayXPositionBuilder ,
621
629
bool supportClearField = false ,
622
630
Set <LogicalKeyboardKey > keyEventsToPropogate = const {},
623
631
VoidCallback onClose,
@@ -633,7 +641,7 @@ mixin SearchFieldMixin<T extends StatefulWidget> on State<T> {
633
641
searchTextFieldController: searchTextFieldController,
634
642
decoration: decoration,
635
643
label: label,
636
- tracking : tracking ,
644
+ overlayXPositionBuilder : overlayXPositionBuilder ,
637
645
onClose: onClose,
638
646
);
639
647
@@ -718,6 +726,7 @@ class _SearchField extends StatelessWidget {
718
726
this .tracking = false ,
719
727
this .decoration,
720
728
this .onClose,
729
+ this .overlayXPositionBuilder,
721
730
});
722
731
723
732
final SearchControllerMixin controller;
@@ -731,30 +740,21 @@ class _SearchField extends StatelessWidget {
731
740
final bool tracking;
732
741
final InputDecoration decoration;
733
742
final VoidCallback onClose;
743
+ final OverlayXPositionBuilder overlayXPositionBuilder;
734
744
735
745
@override
736
746
Widget build (BuildContext context) {
747
+ final textStyle = Theme .of (context).textTheme.subtitle1;
737
748
final searchField = TextField (
738
749
key: searchFieldKey,
739
750
autofocus: true ,
740
751
enabled: searchFieldEnabled,
741
752
focusNode: searchFieldFocusNode,
742
753
controller: searchTextFieldController,
754
+ style: textStyle,
743
755
onChanged: (value) {
744
- if (tracking) {
745
- // Use a TextPainter to calculate the width of the newly entered text.
746
- // TODO(terry): The TextPainter's TextStyle is default (same as this
747
- // TextField) consider explicitly using a TextStyle of
748
- // this TextField if the TextField needs styling.
749
- final painter = TextPainter (
750
- textDirection: TextDirection .ltr,
751
- text: TextSpan (text: value),
752
- );
753
- painter.layout ();
754
-
755
- // X coordinate of the pop-up, immediately to the right of the insertion
756
- // point (caret).
757
- controller.xPosition = painter.width;
756
+ if (overlayXPositionBuilder != null ) {
757
+ controller.xPosition = overlayXPositionBuilder (value, textStyle);
758
758
}
759
759
controller.search = value;
760
760
},
0 commit comments