I have a TextField widget working with ScrollablePositionedList.builder (package).
When the user inputs characters into the TextField it will then automatically scroll the list to that word in my list of widgets which are organized alphabetically.
When there is not an exact match however, I am trying to search alphabetically by each charater input one by one to the closest match. (e.g. so "ca" would scroll to the first word starting with “ca" like "cat" - rather than the first word that just contains "ca" somewhere in say the middle of the word).
I can do this by using if statements comparing character by character - however this appears very inefficient and increased levels of code for increasing potential character lengths input, where no exact match occurs.
QUESTION: As this appears a very standard search method, is there a better pattern / method / standard approach that can achieve the above result and could handle any length range of characters input? I have searched for a solution for Flutter but can't seem to find one.
Thank you!
Here is the relevant section of example code of my current solution to search alphabetically (ie this would need to keep increasing for potential longer matches)...
else if (_inputtedText.length == 2) {
for (int i = 0; i < _expandedTiles.length; i ) {
if (_inputtedText[0] == _expandedTiles[i].tileModel.word![0]) {
if(_inputtedText[1] == _expandedTiles[i].tileModel.word![1]){
_itemScrollController.scrollTo(
curve: Curves.easeInOut,
index: i,
duration: Duration(milliseconds: 2000));
break;
}
}
/// code omitted
/// And a fuller version of code for more context
class _AllWordsState extends State<AllWords> {
final TextEditingController _textEditingController = TextEditingController();
final ItemScrollController _itemScrollController = ItemScrollController();
String _inputtedText = "";
List<Map> _allWords = [];
List<ExpandedTile> _expandedTiles = [];
TileModel _modelTapped = TileModel();
@override
void initState() {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
_textEditingController.addListener(() {
for (int i = 0; i < _expandedTiles.length; i ) {
if (_inputtedText.isEmpty) {
return;
} else if (_inputtedText == _expandedTiles[i].tileModel.word!) {
_itemScrollController.scrollTo(
curve: Curves.easeInOut,
index: i,
duration: Duration(milliseconds: 2000));
return;
}
else if (_inputtedText.length == 1) {
for (int i = 0; i < _expandedTiles.length; i ) {
if (_inputtedText[0] == _expandedTiles[i].tileModel.word![0]) {
_itemScrollController.scrollTo(
curve: Curves.easeInOut,
index: i,
duration: Duration(milliseconds: 2000));
break;
}
}
}
else if (_inputtedText.length == 2) {
for (int i = 0; i < _expandedTiles.length; i ) {
if (_inputtedText[0] == _expandedTiles[i].tileModel.word![0]) {
if(_inputtedText[1] == _expandedTiles[i].tileModel.word![1]){
_itemScrollController.scrollTo(
curve: Curves.easeInOut,
index: i,
duration: Duration(milliseconds: 2000));
break;
}
}
}
}
else if (_expandedTiles[i]
.tileModel
.word!
.contains(_inputtedText)) {
_itemScrollController.scrollTo(
curve: Curves.easeInOut,
index: i,
duration: Duration(milliseconds: 2000));
break;
}
}
});
});
_setUpDatabase();
super.initState();
}
/// code omitted
child: ScrollablePositionedList.builder(
itemScrollController: _itemScrollController,
itemCount: _expandedTiles.length,
itemBuilder: (context, index) {
return buildDisplayBox(
context, index, _expandedTiles, size);
}),
/// code omitted
child: TextField(
controller: _textEditingController,
onChanged: (value) {
_inputtedText = value;
},
/// code omitted
CodePudding user response:
You can user Dart's where
search on any array and startsWith
to look for matches that start with the term:
final myArray = ['abc', 'abd', 'acd', 'bca', 'abe'];
final results = myArray.where((e) => e.startsWith('ab'));
print (results);
The result will be:
(abc, abd, abe)