regex - 以编程方式突出显示 Flutter Richtext 中的字符串匹配项
问题描述
我有一个字符串,其中包含带有@标签的提及,我想创建一个富文本,其中每个标签都包含在带有用户名和 userIds 的提及地图中,并突出显示并使其可点击。
// dummy class
class Reply {
List<dynamic> mentions;
String? text;
Reply({required this.mentions, required this.text});
}
// sample reply
Reply sample = Reply(
mentions: [
{'username': 'sampleUser1', 'userId': '0x123'},
{'username': 'sampleUser2', 'userId': '0x321'}
],
text: 'This text mentions @0x123 as well as @0x321',
);
// replacing all matching ids with the respective usernames
for (var ment in sample.mentions) {
sample.text = sample.text!.replaceAll(ment['userId'], ment['username']);
}
print(sample.text); // This text mentions @sampleUser1 as well as @sampleUser2
这就是我卡住的地方。我想创建一个富文本,以粗体突出显示文本中的用户名并使其可点击。
RichText(
text: TextSpan(
children: 'sample sample' /*sample.text goes here*/
.split(' ') /*find words that start with '@' and include a username that can also be found in the list of mentions*/
.map((word) => TextSpan(
text: word + ' ',
style: TextStyle(
fontWeight:
true /*condition if word is found in mentions*/
? FontWeight.bold
: FontWeight.normal),
recognizer: TapGestureRecognizer()
..onTap =
true /*condition if word is found in mentions*/
? () {
/*do something*/
}
: () {
/*do nothing*/
}))
.toList())),
任何帮助表示赞赏,我会继续尝试,并在我弄清楚时在这里更新。
解决方案
感谢@pskink,我得到了它的工作。
buildTextSpan(String s, List<dynamic>? mentions) {
var regularStyle = //regular style
var mentionStyle = //style with mentions
List<InlineSpan> children = [];
//return regular text if no users have been mentioned
if(mentions == null || mentions.isEmpty){
children.add(TextSpan(text: s, style: regularStyle));
return TextSpan(children: children);
}
s.splitMapJoin(
//only match strings that are prefixed with '@'
//and are contained in the mentions-map at the 'userId'-key that is passed in
//join the regex with 'or' to include all mentions
RegExp(mentions.map((e) => '@'+e['userId']!).join('|')),
//if there's a match, re-add the '@' and grab the username to the userId as provided by the mentions-map
//substring(1) to exclude the @-sign when looking up the value in the map
onMatch: (Match match) {
children.add(TextSpan(
text: '@' + mentions.firstWhere((element) => element['userId'] == match[0]!.substring(1))['username']!,
style: mentionStyle,
//app specific: navigate to user screen and pass the userId
recognizer: TapGestureRecognizer()..onTap = () => //navigation logic));
//return empty string that will not be used but has to be returned due to null-safety
return '';
//add regular textspan on no match
},onNonMatch: (String text) {children.add(TextSpan(
text: text,
style: regularStyle
));
return '';}
);
return TextSpan(children: children);
}
推荐阅读
- php - 我如何指向另一个函数?这可能吗?
- javascript - 记录到控制台按键,包括重复按下
- ios - 忽略组合中的错误
- android - 使用 Flutter 从 Firestore 获取数据以获取角色库主视图
- machine-learning - 如何调整已构建的 ML 预测模型
- python - 数据框和 .csv 上的行终止符 \n 的问题
- javascript - html 中的 FizzBuzz Javascript
- matplotlib - 烛台 ... 使用 mpl_finance
- cuda - 带尖峰的高效 CUDA FFT
- python - 何时使用 while 循环与递归