Flutter中是否有一种简单的方法可以“链接”包含纯文本,电子邮件和Web URL的文本?例如,如果我的文字是My phone number is 099 123 45 67 and my email is test@test.com电话号码,并且电子邮件将显示为可点击的链接。
在Android中,它将是一个衬里:
textView.setAutoLinkMask(Linkify.ALL);
Run Code Online (Sandbox Code Playgroud)
我已经看到在这里提出了类似的问题。该解决方案适用于静态文本,但对于动态文本,解析文本,检测所有URL,电话号码,电子邮件等,并使用TextSpans进行渲染会复杂得多。
小智 8
我为此创建了一个新包:flutter_linkify。它目前仅支持URLS,但是您始终可以通过功能请求在GitHub上提交问题。
Baisc用法:
import 'package:flutter_linkify/flutter_linkify.dart';
Linkify(
onOpen: (url) => print("Clicked $url!"),
text: "Made by https://cretezy.com",
);
Run Code Online (Sandbox Code Playgroud)
感谢@Charles Crete 创建该库。
我只想通过结合 RichText、TextSpan 和 TapGestureRecognizer(都在 Flutter 框架中)在这里添加一个解决方案
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() {
runApp(HyperLinkDemo());
}
class HyperLinkDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RichText(
text: TextSpan(children: [
TextSpan(
text: 'This is a very long text, but you can not click on it. ',
style: TextStyle(fontSize: 20, color: Colors.black)),
TextSpan(
text: 'And this is a clickable text',
style: TextStyle(
fontSize: 20,
color: Colors.blue,
decoration: TextDecoration.underline),
recognizer: TapGestureRecognizer()
..onTap = () {
print('You clicked on me!');
})
])),
),
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
这是结果
这是我实现它的方式 - 使用该buildTextWithLinks函数获取Text带有链接的组件。
它使用 url_launcher 并且当前支持 URL、邮件和电话链接,但可以通过添加更多RegExps 和处理程序轻松扩展。
import 'package:url_launcher/url_launcher.dart';
Text buildTextWithLinks(String textToLink) => Text.rich(TextSpan(children: linkify(textToLink)));
Future<void> openUrl(String url) async {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
const String urlPattern = r'https?:/\/\\S+';
const String emailPattern = r'\S+@\S+';
const String phonePattern = r'[\d-]{9,}';
final RegExp linkRegExp = RegExp('($urlPattern)|($emailPattern)|($phonePattern)', caseSensitive: false);
WidgetSpan buildLinkComponent(String text, String linkToOpen) => WidgetSpan(
child: InkWell(
child: Text(
text,
style: TextStyle(
color: Colors.blueAccent,
decoration: TextDecoration.underline,
),
),
onTap: () => openUrl(linkToOpen),
)
);
List<InlineSpan> linkify(String text) {
final List<InlineSpan> list = <InlineSpan>[];
final RegExpMatch match = linkRegExp.firstMatch(text);
if (match == null) {
list.add(TextSpan(text: text));
return list;
}
if (match.start > 0) {
list.add(TextSpan(text: text.substring(0, match.start)));
}
final String linkText = match.group(0);
if (linkText.contains(RegExp(urlPattern, caseSensitive: false))) {
list.add(buildLinkComponent(linkText, linkText));
}
else if (linkText.contains(RegExp(emailPattern, caseSensitive: false))) {
list.add(buildLinkComponent(linkText, 'mailto:$linkText'));
}
else if (linkText.contains(RegExp(phonePattern, caseSensitive: false))) {
list.add(buildLinkComponent(linkText, 'tel:$linkText'));
} else {
throw 'Unexpected match: $linkText';
}
list.addAll(linkify(text.substring(match.start + linkText.length)));
return list;
}
Run Code Online (Sandbox Code Playgroud)
该功能可以自动检测文本视图中的超链接是什么。您可以根据您的要求修改\nRegx 模式。
\nList<TextSpan> extractText(String rawString) {\nList<TextSpan> textSpan = [];\n\nfinal urlRegExp = new RegExp(\n r"((https?:www\\.)|(https?:\\/\\/)|(www\\.))[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9]{1,6}(\\/[-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)?");\n\ngetLink(String linkString) {\n textSpan.add(\n TextSpan(\n text: linkString,\n style: new TextStyle(color: Colors.blue),\n recognizer: new TapGestureRecognizer()\n ..onTap = () {\n Fluttertoast.showToast(msg: linkString);\n },\n ),\n );\n return linkString;\n}\n\ngetNormalText(String normalText) {\n textSpan.add(\n TextSpan(\n text: normalText,\n style: new TextStyle(color: Colors.black),\n ),\n );\n return normalText;\n}\n\nrawString.splitMapJoin(\n urlRegExp,\n onMatch: (m) => getLink("${m.group(0)}"),\n onNonMatch: (n) => getNormalText("${n.substring(0)}"),\n);\n\nreturn textSpan;}\nRun Code Online (Sandbox Code Playgroud)\n用法
\nchild: SelectableText.rich(\n TextSpan(\n children: extractText(dummyText),\n style: TextStyle(fontSize: _fontSize)),\n )\nRun Code Online (Sandbox Code Playgroud)\n这是结果
\n
\xc2\xa0
| 归档时间: |
|
| 查看次数: |
2053 次 |
| 最近记录: |