How to linkify text in Flutter

▼魔方 西西 提交于 2021-01-21 12:49:52

问题


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 test@test.com 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.


回答1:


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",
);



回答2:


Thank you @Charles Crete for creating that library.

I just want to add one more solution here by combining RichText, TextSpan and TapGestureRecognizer (all are in Flutter framework)

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!');
                    })
            ])),
          ),
        ),
      ),
    );
  }
}

Here is the result




回答3:


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;
}



回答4:


This plugin named linker (https://github.com/best-flutter/linker/blob/master/example/lib/main.dart)

is going to help you.

You can open phone number to call

you can open other system apps or system settings

You can open any 3rd party apps using this package..

you can open email

This package is available in pub.dev ...Search Linker to get it




回答5:


Check this library flutter_autolink_text. Is very similar to flutter_linkify but it adds support to phone number as well.

This is how to use it.

import 'package:flutter_autolink_text/flutter_autolink_text.dart';

AutolinkText(
    text: ...,
    textStyle: TextStyle(color: Colors.black),
    linkStyle: TextStyle(color: Colors.blue),
    onWebLinkTap: (link) => print('Clicked: ${link}'),
    onEmailTap: (link) => print('Clicked: ${link}'),
    onPhoneTap: (link) => print('Clicked: ${link}')
);


来源:https://stackoverflow.com/questions/51985111/how-to-linkify-text-in-flutter

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!