【问题标题】:How to change text color according to valid(@mentions) and all hashtags?如何根据有效(@mentions)和所有主题标签更改文本颜色?
【发布时间】:2021-07-07 17:42:21
【问题描述】:

我想在文本中以不同颜色显示主题标签和有效提及。


我得到了有关此代码的帮助,该代码仅适用于主题标签

RichText _convertHashtag(String text) {
  List<String> split = text.split(RegExp("#"));
  List<String> hashtags = split.getRange(1, split.length).fold([], (t, e) {
    var texts = e.split(" ");
    if (texts.length > 1) {
      return List.from(t)
        ..addAll(["#${texts.first}", "${e.substring(texts.first.length)}"]);
    }
    return List.from(t)..add("#${texts.first}");
  });
  return RichText(
    text: TextSpan(
      children: [TextSpan(text: split.first)]..addAll(hashtags
          .map((text) => text.contains("#")
              ? TextSpan(text: text, style: TextStyle(color: Colors.blue))
              : TextSpan(text: text))
          .toList()),
    ),
  );
}

我修改如下:


  List valid_mentions = ['@mention1', '@mention2'];//these are the valid mention

  RichText _convertHashtag(String text) {
    List<String> split = text.split(RegExp("#|@"));
    List<String> hashtags = split.getRange(1, split.length).fold([], (t, e) {
      var texts = e.split(" ");

      //here adding `@` sign and `#` sign to the given texts and storing them in the `hashtags` list
      if (texts.length > 1) {
        if (valid_mentions.contains(texts.first))
          return List.from(t)
            ..addAll(["@${texts.first}", "${e.substring(texts.first.length)}"]);
        else if (text.contains('@${texts.first}')) {
          return List.from(t)
            ..addAll(["@${texts.first}", "${e.substring(texts.first.length)}"]);
        } else
          return List.from(t)
            ..addAll(["#${texts.first}", "${e.substring(texts.first.length)}"]);
      } else {
        if (valid_mentions.contains(texts.first))
          return List.from(t)..addAll(["@${texts.first}"]);
        else if (text.contains('@${texts.first}')) {
          return List.from(t)..addAll(["@${texts.first}"]);
        } else
          return List.from(t)..addAll(["#${texts.first}"]);
      }
    });
    return RichText(
      text: TextSpan(
        children: [TextSpan(text: split.first)]..addAll(hashtags.map((text) {
            return text.contains("@")
                ? valid_mentions.contains(text)
                    ? //checking if the mention is valid
                    TextSpan(
                        text: text,
                        recognizer: TapGestureRecognizer()
                          ..onTap = () {
                            print(text);
                          },
                        style: TextStyle(color: Colors.blue))
                    : TextSpan(
                        text: text,
                      )
                : text.contains("#")
                    ? TextSpan(
                        text: text,
                        recognizer: TapGestureRecognizer()
                          ..onTap = () {
                            print(text);
                          },
                        style: TextStyle(color: Colors.blue))
                    : TextSpan(
                        text: text,
                      );
          }).toList()),
      ),
    );
  }

我能够进行所需的更改,但我相信这不是一种优化的方式,并且有很多样板代码。我该如何优化它?

输入:“我喜欢#flutter #android @mention1 @mention2 @mention3”

输出:“我爱 #flutter #android @mention1 @mention2 @mention3 “

这里@mention3 没有超链接,因为它不是有效的提及。

【问题讨论】:

    标签: flutter dart dart-pub


    【解决方案1】:

    据我了解,您希望在字符串中突出显示主题标签和提及(预先存储在列表中)。

    让我把它分成两部分,第一部分是从文本中提取主题标签和提及。

    List<String> getAllHashtags(String text) {
      final regexp = RegExp(r'\#[a-zA-Z0-9]+\b()');
    
      List<String> hashtags = [];
    
      regexp.allMatches(text).forEach((element) {
        if (element.group(0) != null) {
          hashtags.add(element.group(0).toString());
        }
      });
    
      return hashtags;
    }
    
    List<String> getAllMentions(String text) {
      final regexp = RegExp(r'\@[a-zA-Z0-9]+\b()');
    
      List<String> mentions = [];
    
      regexp.allMatches(text).forEach((element) {
        if (element.group(0) != null) {
          mentions.add(element.group(0).toString());
        }
      });
    
      return mentions;
    }
    

    上述代码 sn-p 将成功地从给定句子中提取主题标签和提及,并将其作为列表返回。

    下一步是使用不同的 TextSpan 构建 RichText。

    RichText buildHighlightedText(String text) {
      // clean the text
      text = cleanText(text);
    
      List<String> validMentions = ["@mention1", "@mention2"];
      
      List<String> hashtags = getAllHashtags(text);
      List<String> mentions = getAllMentions(text);
    
      List<TextSpan> textSpans = [];
    
      text.split(" ").forEach((value) {
        if (hashtags.contains(value)) {
          textSpans.add(TextSpan(
            text: '$value ',
            style: TextStyle(color: Colors.amber, fontWeight: FontWeight.bold),
          ));
        } else if (mentions.contains(value) && validMentions.contains(value)) {
          textSpans.add(TextSpan(
            text: '$value ',
            style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
          ));
        } else {
          textSpans.add(TextSpan(text: '$value '));
        }
      });
    
      return RichText(text: TextSpan(children: textSpans));
    }
    

    文本已被空格分隔,并过滤主题标签/提及并为每个返回不同样式的 TextSpans。这是一种更简洁、更简洁的方式来满足您的需求。

    这是一个例子:

    编辑:

    为了解析没有空格的主题标签,我们需要在每个实例前面添加一个空格。

    String cleanText(String text) {
      text = text.replaceAllMapped(
          RegExp(r'\w#+'), (Match m) => "${m[0]?.split('').join(" ")}");
    
      text = text.replaceAllMapped(
          RegExp(r'\w@+'), (Match m) => "${m[0]?.split('').join(" ")}");
    
      return text;
    }
    

    【讨论】:

    • 谢谢?,效果很好。还有一件事,如果我们希望#hello#world 或@mention1@mention2 成为有效的主题标签并提及,需要进行哪些更改。由于我们使用的是 text.split(" ").forEach((value) ,因此它们不会拆分并且不会被考虑。
    • 确实如此。在这种情况下,必须将文本编辑为在值前面有空格。我已经编辑了我的答案。 @kanwarmanraj
    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    相关资源
    最近更新 更多