如何突出显示搜索结果中的匹配项

时间:2021-04-16 20:03:38

标签: flutter dart

我试图让用户搜索,这工作正常,但现在我希望搜索结果的字符是 Fontweight 粗体。但苦苦挣扎。 这是我的代码

class Openmyprofil extends StatefulWidget {
  final TextEditingController searchinginput;

  const Openmyprofil({Key key, this.searchinginput}) : super(key: key);

  @override
  _OpenmyprofilState createState() => _OpenmyprofilState();
}

class _OpenmyprofilState extends State<Openmyprofil> {
  List _allResults = [];
  List _resultsList = [];

  Future resultsLoaded;
  bool nosuerfound = false;
  var titles;
  @override
  void initState() {
    super.initState();
    widget.searchinginput.addListener(_onsearchChanged);
    setState(() {
      nosuerfound = true;
    });
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    resultsLoaded = getusers();
  }

  _onsearchChanged() {
    print(_resultsList);
    print(_allResults);
    print(searchResults);
    setState(() {
      nosuerfound = false;
    });
    searchResults();
  }

  @override
  void dispose() {
    widget.searchinginput.removeListener(_onsearchChanged());
    super.dispose();
  }

  searchResults() {
    var showResults = [];
    if (widget.searchinginput.text != "") {
      for (var tripsnapshot in _allResults) {
        titles = tripsnapshot;
        var title = DatbaseService.instance
            .userDataFromSnapshot(tripsnapshot)
            .username
            .toLowerCase();
        if (title.contains(widget.searchinginput.text.toLowerCase())) {
          setState(() {
            nosuerfound = true;
          });
          showResults.add(tripsnapshot);
          print(tripsnapshot);
        }
      }
    } else {
      setState(() {
        nosuerfound = true;
      });
      showResults = List.from(_allResults);
    }
    setState(() {
      _resultsList = showResults;
    });
  }

  getusers() async {
    var firestore = FirebaseFirestore.instance;
    QuerySnapshot qn = await firestore.collection('meinprofilsettings').get();
    setState(() {
      _allResults = qn.docs;
    });
    searchResults();
    return "Complete";
  }

  @override
  Widget build(BuildContext context) {
    final user = Provider.of<Userforid>(context);

    if (nosuerfound == true) {
      return Container(
          child: ListView.builder(
              itemCount: _resultsList.length,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                  onTap: () {
                    DatbaseService.instance.createorGetConversation(
                        user.uid, _resultsList[index].id,
                        (String _conversationID) {
                      NavigationService.instance.navigateToRoute(
                        MaterialPageRoute(builder: (context) {
                          return MeineBeitraege(
                              _conversationID,
                              _resultsList[index].id,
                              _resultsList[index].data()['username'],
                              _resultsList[index].data()['url'],
                              _resultsList[index].data()['email']);
                        }),
                      );
                    });
                  },
                  leading: Container(
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(60),
                      child: Container(
                          height: 50,
                          width: 50,
                          decoration: BoxDecoration(
                            color: Colors.white,
                          ),
                          child: _resultsList[index].data()['url'] != null &&
                                  _resultsList[index].data()['url'] !=
                                      "profilepictureer"
                              ? Image.network(
                                  _resultsList[index].data()['url'],
                                  fit: BoxFit.cover,
                                )
                              : Image.asset(
                                  'assets/profilepictureer.png') // Your widget is here when image is no available.
                          ),
                    ),
                    decoration: new BoxDecoration(
                      shape: BoxShape.circle,
                      border: new Border.all(color: Colors.black, width: 4),
                    ),
                  ),
                  title: Text(_resultsList[index].data()['username'],
                      style: widget.searchinginput.text.contains(
                                  _resultsList[index].data()['username']) ||
                              widget.searchinginput.text.contains(
                                  _resultsList[index].data()['username'])
                          ? TextStyle(fontWeight: FontWeight.bold)
                          : null),
                  subtitle: Text(_resultsList[index].data()['email']),
                );
              }));
    } else {
      return Padding(
        padding: const EdgeInsets.fromLTRB(0, 30, 0, 0),
        child: Container(
            child: Text(
          "No user found",
          style: TextStyle(fontSize: 16),
        )),
      );
    }
  }
}

所以 widget.searchinginput 是我的 TextEditingController,我想要的是如果用户输入 Mi 我在 _resultlist 中有一个名字 Mike 那么 Mike 的 Mi 应该是粗体然后用户输入 Mik ,Mik in resultless 应该是大胆的希望任何人都可以提供帮助。 如果您需要更多信息,请发表评论

1 个答案:

答案 0 :(得分:0)

据我了解您的问题,您需要通过对其应用自定义样式来突出显示正在搜索的文本,如果您要求将字体粗细更改为粗体。

要使文本的某些部分与其他部分不同,您需要使用 Text.rich 小部件,并找出需要突出显示的部分,我建议使用 RegExp

我制作了一个小部件,可以帮助您实现您的要求:

class HighlightedMatchesText extends StatelessWidget {
  final String searchString;
  final String content;

  const HighlightedMatchesText({
    Key? key,
    required this.searchString,
    required this.content,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final matches = searchString.isEmpty
        ? <RegExpMatch>[]
        : RegExp(searchString).allMatches(content).toList();
    final parts = <InlineSpan>[];
    if (matches.isEmpty) {
      parts.add(TextSpan(text: content));
    } else {
      var i = 0;
      var matchIndex = 0;
      while (true) {
        // if we moved through all matches, we can stop, and the rest
        // of the text is not going to be bold
        if (matchIndex >= matches.length) {
          final end = content.substring(matches.last.end);
          if (end.isNotEmpty) {
            parts.add(TextSpan(text: content.substring(matches.last.end)));
          }
          break;
        }
        final match = matches[matchIndex];
        // if the start of the current match is after the current index
        // then this parts should not be bold until the start of the match
        if (match.start > i) {
          final slice = content.substring(i, match.start);
          parts.add(TextSpan(text: slice));
          i = match.start;
          continue;
        }
        // this part here is where it gets bold
        final slice = content.substring(match.start, match.end);
        parts.add(TextSpan(
          text: slice,
          style: const TextStyle(fontWeight: FontWeight.bold),
        ));
        matchIndex += 1;
        i = match.end;
      }
    }

    return Text.rich(
      TextSpan(
        children: parts,
      ),
    );
  }
}

使用它代替当前的 Text 小部件。 searchString 是您要搜索的内容,content 是要显示的内容,在您的情况下,我认为它是用户名。

像这样使用它:

HighlightedMatchesText(
  searchString: widget.searchinginput.text,
  content: _resultsList[index].data()['username'],
);