Flutter-用小部件替换子字符串

时间:2020-02-20 16:40:59

标签: flutter gesturedetector

我正在使用Flutter构建应用程序,但是我的一个小部件遇到了一些麻烦。我正在从API端点获取JSON响应,以便在帖子上构建评论,但是我需要能够包含字符串的一部分并将其包装在GestureDetector中,以便处理“ @提及”

例如:我有一个字符串hey there @MattChris how are you?,我需要能够将@MattChris包裹在GestureDetector中。

此刻,我解析传入的字符串,并提供一个列表,其中包含实际注释中每个以空格分隔的单词。像这样:

List<Widget> comment = new List();

outer: for (String word in json['content'].toString().split(" ")) {
  if (word != null && word.isNotEmpty) {
    if (word.startsWith('@')) {

      comment.add(GestureDetector(
        onTap: goToProfile,
        child: Text(word + ' ')
      );

    } else {
      comment.add(Text(word + ' '));
    }
  }
}

现在唯一的问题是,有很多额外的元素占用了内存,并且难以确保文本以我期望的方式包装。我已经看到了答案here,但是我不确定如何确保文本像Text小部件中的一个字符串一样自动换行。

2 个答案:

答案 0 :(得分:0)

我能够找到一个可行的解决方案。再次阅读我喜欢的实现,并查看注释,我决定使用递归函数:

List<TextSpan> _mentionParser(String message, Iterable<dynamic> mentions) {
  if (message == null || message.isEmpty) // Don't return anything if there is no message.
    return [];

  for (Map<String, dynamic> mention in mentions) { // Loop through the list of names to replace
    if (message.contains("@${mention['username']}")) { // If the message contains the name to replace
      List<TextSpan> _children = [];
      String preUsernameMessage = message.substring(0, message.indexOf("@${mention['username']}")).trimLeft(); // Get everything before the mention
      if (preUsernameMessage != null && preUsernameMessage.isNotEmpty)
        _children.add(TextSpan(children: _mentionParser(preUsernameMessage, mentions))); // if it isn't empty, recurse and add to the list

      _children.add( // Always add the display name to the list
        TextSpan(
          text: "${mention['display_name']}".trim(),
          style: TextStyle(color: Color(0xff2e6da4)),
          recognizer: TapGestureRecognizer()
            ..onTap = () => {gotoProfile(json['username'])}
        )
      );

      String postUsernameMessage = message.substring(message.indexOf("@${mention['username']}") + "@${mention['username']}".length, message.length).trimRight(); // Get everything after the mention
      if (postUsernameMessage != null && postUsernameMessage.isNotEmpty) // If it isn't empty, recurse and add it to the list
        _children.add(TextSpan(children: _mentionParser(postUsernameMessage, mentions)));

      return _children; // return the constructed list
    }
  }
  return [TextSpan(text: message)]; // If the string didn't contain any of the strings to replace, then just return the message as passed.
}

然后我将其称为childrenTextSpan上的Text.rich变量。花了一些时间,但我能够使实施工作正常!

答案 1 :(得分:0)

public String method(String str) {
if (str != null && str.length() > 0 && str.charAt(str.length() - 1) == 'x') {
    str = str.substring(0, str.length() - 1);
}
return str; // to remove last character
}