2025-07-21 15:46:30 +08:00

97 lines
2.7 KiB
Dart

/// 富文本emoj表情展示
/// 通过实现[Text.rich]展示文本、emoji、自定义表情、URL等
library;
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'package:url_launcher/url_launcher.dart';
class RichTextUtil {
static getRichText(String text, {Color color = Colors.black}) {
List<InlineSpan> textSpans= [];
// 网址正则
String urlExpString = r"(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?";
// 表情正则
String emojExpString = r"\[.{1,4}?\]";
RegExp reg = RegExp('$urlExpString|$emojExpString');
if(reg.hasMatch(text)) {
Iterable<RegExpMatch> matches = reg.allMatches(text);
int index = 0;
int count = 0;
for(var match in matches) {
count++;
String c = text.substring(match.start, match.end);
// 匹配在首位
if(index == match.start) {
index = match.end;
}
// 匹配不在首位
else if(index < match.start) {
String leftStr = text.substring(index, match.start);
index = match.end;
textSpans.add(
TextSpan(
text: getSpaceText(leftStr),
)
);
}
// 匹配到表情...
if(RegExp(emojExpString).hasMatch(c)) {
// ...
}
// 匹配到网址
else if(RegExp(urlExpString).hasMatch(c)) {
textSpans.add(
TextSpan(
text: getSpaceText(c),
style: const TextStyle(color: Colors.blue,),
recognizer: TapGestureRecognizer()
..onTap = () async {
// await launchUrl(Uri.parse('https://flutter.cn'));
await launchUrl(Uri.parse(c));
},
)
);
}
// 是否最后一个表情,且后面是否有字符串
if(matches.length == count && text.length > index) {
String rightStr = text.substring(index, text.length);
textSpans.add(
TextSpan(
text: getSpaceText(rightStr),
)
);
}
}
}else {
textSpans.add(
TextSpan(
text: getSpaceText(text),
)
);
}
// 生成富文本
return Text.rich(
TextSpan(
style: TextStyle(color: color),
children: textSpans
),
);
}
// 内容
static String getSpaceText(String text) {
if(text.isEmpty) return text;
String spaceWord = '';
for(var elem in text.runes) {
spaceWord += String.fromCharCode(elem);
spaceWord += '\u200B';
}
return spaceWord;
}
}