flutter聊天界面-Text富文本表情emoji、url、号码展示
Text富文本表情emoji展示,主要通过实现Text.rich展示文本、emoji、自定义表情、URL等
一、Text及TextSpan
Text用于显示简单样式文本
TextSpan它代表文本的一个“片段”,不同“片段”可按照不同的样式显示。
示例片段
Text.rich(TextSpan(
children: [
TextSpan(
text: "Home: "
),
TextSpan(
text: "https://flutterchina.club",
style: TextStyle(
color: Colors.blue
),
recognizer: _tapRecognizer
),
]
))
二、Text富文本表情emoji展示
Text富文本表情emoji展示主要通过RegExp匹配url、手机号码
自定义表情的正则表达式:
String emojExpString = r"\[.{1,4}?\]";
链接URL的正则表达式:
String urlExpString =
r"(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?";
具体实现代码如下
// 富文本
class CommChatRichTextHelper {
//图文混排
static getRichText(String text) {
List<InlineSpan> textSapns = [];
String urlExpString =
r"(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?";
String emojExpString = r"\[.{1,4}?\]";
RegExp exp = RegExp('$urlExpString|$emojExpString');
//正则表达式是否在字符串[input]中有匹配。
if (exp.hasMatch(text)) {
Iterable<RegExpMatch> matches = exp.allMatches(text);
int index = 0;
int count = 0;
for (var matche in matches) {
count++;
String c = text.substring(matche.start, matche.end);
//匹配到的东西,如表情在首位
if (index == matche.start) {
index = matche.end;
}
//匹配到的东西,如表情不在首位
else if (index < matche.start) {
String leftStr = text.substring(index, matche.start);
index = matche.end;
textSapns.add(
TextSpan(
text: spaceWord(leftStr),
style: getDefaultTextStyle(),
),
);
}
//匹配到的网址
if (RegExp(urlExpString).hasMatch(c)) {
textSapns.add(
TextSpan(
text: spaceWord(c),
style:
TextStyle(color: ColorUtil.hexColor(0x3b93ff), fontSize: 16),
recognizer: TapGestureRecognizer()
..onTap = () async {
//打开浏览器
print(c);
},
),
);
}
//匹配到的表情
else if (RegExp(emojExpString).hasMatch(c)) {
//[偷笑] 去掉[] = 偷笑
String emojiString = c;
textSapns.add(
WidgetSpan(
style: const TextStyle(height: 1.5),
//判断表情是否存在
child: CommonChatEmoji.emojiIsContain(emojiString)
? ImageHelper.imageNetwork(
imageUrl:
"${CommonChatEmoji.findEmojiItem(emojiString)?.url}",
width: 22,
height: 22,
)
: Text(
"${c}",
style: getDefaultTextStyle(),
),
),
);
}
//是否是最后一个表情,并且后面是否有字符串
if (matches.length == count && text.length > index) {
String rightStr = text.substring(index, text.length);
textSapns.add(
TextSpan(
text: spaceWord(rightStr),
style: getDefaultTextStyle(),
),
);
}
}
} else {
textSapns.add(
TextSpan(
text: spaceWord(text),
style: getDefaultTextStyle(),
),
);
}
return Text.rich(TextSpan(children: textSapns));
}
static TextStyle getDefaultTextStyle() {
return TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.normal,
color: ColorUtil.hexColor(0x555555),
decoration: TextDecoration.none,
);
}
static String spaceWord(String text) {
if (text.isEmpty) return text;
String spaceWord = '';
for (var element in text.runes) {
spaceWord += String.fromCharCode(element);
spaceWord += '\u200B';
}
return spaceWord;
}
}
使用Text.rich的Widget的聊天文本气泡
class ChatCellTextElem extends StatefulWidget {
const ChatCellTextElem({
Key? key,
required this.chatMessage,
}) : super(key: key);
final CommonChatMessage chatMessage;
State<ChatCellTextElem> createState() => _ChatCellTextElemState();
}
class _ChatCellTextElemState extends State<ChatCellTextElem> {
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10.0),
child: buildTextContent(),
);
}
Widget buildTextContent() {
// 富文本
return CommChatRichTextHelper.getRichText("${widget.chatMessage.text ?? ""}");
}
}
三、小结
flutter聊天界面-Text富文本表情emoji、url、号码展示,主要实现Text富文本表情emoji展示主要通过RegExp匹配url、手机号码等
学习记录,每天不停进步。