Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to linkify text in Flutter

Tags:

flutter

dart

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.

like image 860
Egemen Avatar asked Aug 23 '18 11:08

Egemen


People also ask

How do you hyperlink Text in Flutter?

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.

How do you color specific Text in Flutter?

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 do I make selectable Text Flutter?

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.") ] ) )


2 Answers

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",
);
like image 53
Charles Crete Avatar answered Oct 03 '22 03:10

Charles Crete


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;
}
like image 45
splintor Avatar answered Oct 03 '22 05:10

splintor