Is there an easy way in Flutter to 'linkify' a text that might contain a mix of plain text, emails and web URLs? E.g. if my text is My phone number is 099 123 45 67 and my email is [email protected] the phone number and the email would be rendered as clickable links.
In Android it would be a one liner:
textView.setAutoLinkMask(Linkify.ALL);
I've seen that a similar question has been asked here. That solution would work fine for static texts, but for dynamic texts it would be a lot more complicated to parse the text, detect all URLs, phone numbers, emails etc. and use TextSpans to render them accordingly.
Turn Text URL to Clickable link using linkify linkify Flutter plugin can turn text URL and email to a clickable inline text. First add flutter_linkify plugin to your project. Next import to the file which you are going to implement the code. Linkify( onOpen: (link) { print("Linkify link = ${link.
Step 1: Locate the file where you have placed the Text widget. Step 2: Inside the Text widget, add the Style parameter and assign the TextStyle widget. Step 3: Inside the TextStyle widget, add the color parameter and set the color of your choice.
How to Add Selectable and Copyable RichText widget in Flutter: SelectableText. rich( TextSpan( style: TextStyle(fontSize: 20), children: [ TextSpan(text:"Hello this is FlutterCampus"), TextSpan(text:"and you are making selectable and copyable text.") ] ) )
I created a new package for this: flutter_linkify. It currently only supports URLS, but you can always submit an issue on GitHub with feature requests.
Baisc usage:
import 'package:flutter_linkify/flutter_linkify.dart';
Linkify(
onOpen: (url) => print("Clicked $url!"),
text: "Made by https://cretezy.com",
);
Here is how I implemented it - use the buildTextWithLinks function to get a Text component with links.
It uses url_launcher and currnetly supports URL, mail and phone links, but can easily be expanded by adding more RegExps and handlers.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With