97 lines
2.7 KiB
Dart
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;
|
|
}
|
|
}
|