Flutter - 用小部件替换子字符串
Flutter - Replace a subsstring with a Widget
我正在构建一个带有 flutter 的应用程序,但我在使用我的一个小部件时遇到了一些问题。我从 API 端点收到 JSON 响应,以便在帖子上建立评论,但我需要能够获取字符串的一部分并将其包装在 GestureDetector
中,为了处理“@提及”。
例如:我有字符串 hey there @MattChris how are you?
我需要能够将 @MattChris
包装在 GestureDetector
.
中
目前,我解析传入的字符串并提供一个列表,其中包含来自实际评论的每个 space 分隔的单词。像这样:
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
小部件中的一个字符串一样。
我找到了可行的解决方案。再次阅读我喜欢的实现,并查看评论,我决定使用递归函数:
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.
}
然后我将其称为 Text.rich
内 TextSpan
上的 children
变量。这花了一些时间,但我能够让实施工作!
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
}
我正在构建一个带有 flutter 的应用程序,但我在使用我的一个小部件时遇到了一些问题。我从 API 端点收到 JSON 响应,以便在帖子上建立评论,但我需要能够获取字符串的一部分并将其包装在 GestureDetector
中,为了处理“@提及”。
例如:我有字符串 hey there @MattChris how are you?
我需要能够将 @MattChris
包装在 GestureDetector
.
目前,我解析传入的字符串并提供一个列表,其中包含来自实际评论的每个 space 分隔的单词。像这样:
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
小部件中的一个字符串一样。
我找到了可行的解决方案。再次阅读我喜欢的实现,并查看评论,我决定使用递归函数:
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.
}
然后我将其称为 Text.rich
内 TextSpan
上的 children
变量。这花了一些时间,但我能够让实施工作!
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
}