import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class LinkText extends StatelessWidget {
final String text;
final TextStyle? style;
final TextStyle? linkStyle;
const LinkText({
super.key,
required this.text,
this.style,
this.linkStyle,
});
@override
Widget build(BuildContext context) {
// ??【超嚴格正則】能識別 http/https/www/普通域名,且不會誤判普通文字
final regExp = RegExp(
r'''(https?:\/\/[^\s]+)|''' // http/https 鏈接
r'''(www\.[a-z0-9\-]+\.[^\s]+)|''' // www 開頭鏈接
r'''([a-z0-9\-]+\.(com|cn|net|org|io|app|dev|top|xyz|cc|co|gov|edu)(\/[^\s]*)?)''', // 純域名(不帶http/www)
caseSensitive: false,
);
final List<TextSpan> children = [];
final matches = regExp.allMatches(text);
int start = 0;
for (final match in matches) {
// 普通文本
if (match.start > start) {
children.add(TextSpan(
text: text.substring(start, match.start),
style: style,
));
}
// 鏈接文本
final link = text.substring(match.start, match.end);
children.add(TextSpan(
text: link,
style: linkStyle ??
const TextStyle(
color: Colors.blue,
decoration: TextDecoration.underline,
height: 1.3,
),
recognizer: TapGestureRecognizer()..onTap = () => _openUrl(link),
));
start = match.end;
}
// 剩余文本
if (start < text.length) {
children.add(TextSpan(
text: text.substring(start),
style: style,
));
}
return RichText(
text: TextSpan(
style: style ??
const TextStyle(
color: Colors.black87,
fontSize: 15,
),
children: children,
),
);
}
// 打開鏈接(自動補全協議)
Future<void> _openUrl(String url) async {
String targetUrl = url;
if (!url.startsWith(RegExp(r'https?://'))) {
targetUrl = 'https://$url';
}
final uri = Uri.parse(targetUrl);
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
}
}
}
超鏈接識別,http開頭和不是http開頭常用的一些
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。