How to create a hyperlink in Flutter widget?

Flutter

Flutter Problem Overview


I would like to create a hyperlink to display in my Flutter app.

The hyper link should be embedded in a Text or similar text views like:

The last book bought is <a href='#'>this</a>

Any hint to do this?

Flutter Solutions


Solution 1 - Flutter

Just wrap an InkWell around a Text widget and supply an UrlLauncher (from the service library) to the onTap attribute. Install UrlLauncher as a Flutter package before using it below.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';


void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('UrlLauncher'),
        ),
        body: new Center(
          child: new InkWell(
              child: new Text('Open Browser'),
              onTap: () => launch('https://docs.flutter.io/flutter/services/UrlLauncher-class.html')
          ),
        ),
      ),
    );
  }
}

You can supply a style to the Text widget to make it look like a link.

Update

After looking into the issue a little I found a different solution to implement the 'in line' hyperlinks you asked for. You can use the RichText Widget with enclosed TextSpans.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('UrlLauchner'),
        ),
        body: new Center(
          child: new RichText(
            text: new TextSpan(
              children: [
                new TextSpan(
                  text: 'This is no Link, ',
                  style: new TextStyle(color: Colors.black),
                ),
                new TextSpan(
                  text: 'but this is',
                  style: new TextStyle(color: Colors.blue),
                  recognizer: new TapGestureRecognizer()
                    ..onTap = () { launch('https://docs.flutter.io/flutter/services/UrlLauncher-class.html');
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

This way you can actually highlight one word and make a hyperlink out of it ;)

Solution 2 - Flutter

Flutter doesn't have built-in hyperlink support but you can fake it yourself. There's an example in the Gallery's drawer.dart. They use a RichText widget containing a coloured TextSpan, which has a recognizer attribute to handle taps:

        RichText(
          text: TextSpan(
            children: [
              TextSpan(
                style: bodyTextStyle,
                text: seeSourceFirst,
              ),
              TextSpan(
                style: bodyTextStyle.copyWith(
                  color: colorScheme.primary,
                ),
                text: repoText,
                recognizer: TapGestureRecognizer()
                  ..onTap = () async {
                    final url = 'https://github.com/flutter/gallery/';
                    if (await canLaunch(url)) {
                      await launch(
                        url,
                        forceSafariVC: false,
                      );
                    }
                  },
              ),
              TextSpan(
                style: bodyTextStyle,
                text: seeSourceSecond,
              ),
            ],
          ),

enter image description here

enter image description here

Solution 3 - Flutter

You can wrap your Text in a GestureDetector or InkWell and handle click in onTap(). If you want to launch a url, you can use url_launcher package.

GestureDetector(
  child: Text("Click here", style: TextStyle(decoration: TextDecoration.underline, color: Colors.blue)),
  onTap: () async {
    const url = 'https://www.google.com';
    if (await canLaunch(url)) launch(url);
  },
)

enter image description here

Solution 4 - Flutter

You can use package flutter_linkify
https://pub.dev/packages/flutter_linkify
Just want to provide another option.
Package will divide your text and highlight http/https automatically
Combine plugin url_launcher you can launch url
You can check example below:

enter image description here

full code below

import 'package:flutter/material.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'dart:async';

import 'package:url_launcher/url_launcher.dart';

void main() => runApp(new LinkifyExample());

class LinkifyExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
	return new MaterialApp(
	  title: 'flutter_linkify example',
	  home: Scaffold(
		appBar: AppBar(
		  title: Text('flutter_linkify example'),
		),
		body: Center(
		  child: Linkify(
			onOpen: _onOpen,
			text: "Made by https://cretezy.com \n\nMail: [email protected] \n\n  this is test http://pub.dev/ ",
		  ),
		),
	  ),
	);
  }

  Future<void> _onOpen(LinkableElement link) async {
	if (await canLaunch(link.url)) {
	  await launch(link.url);
	} else {
	  throw 'Could not launch $link';
	}
  }
}

Solution 5 - Flutter

If you want to make it look even more like a link, you can add underline:

new Text("Hello Flutter!", style: new TextStyle(color: Colors.blue, decoration: TextDecoration.underline),)

and the result:

enter image description here

Solution 6 - Flutter

You can use Link Text https://pub.dev/packages/link_text and use it like

 final String _text = 'Lorem ipsum https://flutter.dev\nhttps://pub.dev'; 
 @override
 Widget build(BuildContext context) {
 return Scaffold(
     body: Center(
      child: LinkText(
        text: _text,
        textAlign: TextAlign.center,
      ),
    ),
  );
}

Solution 7 - Flutter

flutter link widget

In Flutter 2.0, the Link widget was introduced. Use this widget to launch webpages and also navigate to new screens in your app. you need to use the url_launcher package before using it.

url_launcher: ^6.0.8

For More Information

Link(
              uri: Uri.parse('https://androidride.com'),
              //target: LinkTarget.self,
              builder: (context, followLink) {
                return RichText(
                  text: TextSpan(children: [
                    TextSpan(
                      text: 'Click here: ',
                      style: TextStyle(
                        fontSize: 20,
                        color: Colors.black,
                      ),
                    ),
                    TextSpan(
                      text: 'AndroidRide',
                      style: TextStyle(
                        color: Colors.blue,
                        decoration: TextDecoration.underline,
                        fontWeight: FontWeight.bold,
                        fontSize: 21,
                      ),
                      recognizer: TapGestureRecognizer()
                        ..onTap = followLink,
                    ),
                  ]),
                );
              }),
        ),
        SizedBox(
          height: 20,
        ),
        Link(
          uri: Uri.parse('/second'),
          builder: (context, followLink) {
            return InkWell(
              onTap: followLink,
              child: Text(
                'Go to Second Screen',
                style: TextStyle(
                  fontSize: 20,
                  color: Colors.blue,
                  decoration: TextDecoration.underline,
                ),
              ),
            );
          },
        ),

Solution 8 - Flutter

You could use the flutter_html plugin if you want to have more advanced text capabilities:

Html(
  data: 'The last <i><u><b>book</b></u></i> bought is <a href="#">this</a>',
  onLinkTap: (url, context, attrs, element) {
    // Handle link tapped...
  },
)

This is just the tip of the iceberg of capabilities with this plugin.

Just a thought: You could even host parts of your flutter app online as html and render them in flutter as widgets with this plugin.

Solution 9 - Flutter

An alternative (or not) way to put clickable links in your app (for me it just worked that way):

1 - Add the url_launcher package in your pubspec.yaml file

(the package version 5.0 didn't work well for me, so I'm using the 4.2.0+3).

dependencies:
  flutter:
    sdk: flutter
  url_launcher: ^4.2.0+3

2 - Import it and use as below.

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

void main() {
  runApp(MaterialApp(
    title: 'Navigation Basics',
    home: MyUrl(),
  ));
}

class MyUrl extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Url Launcher'),
      ),
      body: Center(
        child: FlatButton(
          onPressed: _launchURL,
          child: Text('Launch Google!',
              style: TextStyle(fontSize: 17.0)),
        ),
      ),
    );
  }

  _launchURL() async {
    const url = 'https://google.com.br';
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }
}

Solution 10 - Flutter

The answers to this question that suggest using RichText with a TextSpan + GestureRecognizer are all functionally correct, but from the UX perspective, they do not provide feedback to the user responding to the touch. To maintain consistency with other Material widgets, you could use a similar approach, but use a WidgetSpan + InkWell instead.

This example uses the url_launcher package and an unstyled InkWell, but you can customize as you see fit:

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

class TextWithLink extends StatelessWidget {
  const TextWithLink({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    const textStyle = TextStyle(color: Colors.black); // default style for all text
    return RichText(
      text: TextSpan(
        style: textStyle,
        children: [
          const TextSpan(
            text: 'The last book bought is ',
          ),
          WidgetSpan(
              alignment: PlaceholderAlignment.middle,
              child: InkWell(
                  onTap: () => _launchUrl('https://url-to-launch.com'),
                  child: Text('this',
                      style: textStyle.merge(const TextStyle(
                          color: Colors.blue, fontWeight: FontWeight.bold))))), // override default text styles with link-specific styles
        ],
      ),
    );
  }

  _launchUrl(String url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }
}

Solution 11 - Flutter

Here is a turn-key package https://pub.dev/packages/link_text

child: LinkText(
  'Hello check http://google.com',
  textStyle: ...,
),

Safer to use a library for this kind of complexity

Pros:

  • takes in the entire string as a single param
  • parses the links and renders them into the UI as clickable , inline with the non-clickable text
  • no complex RichText structure required

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTaylorRView Question on Stackoverflow
Solution 1 - FlutterRainer WittmannView Answer on Stackoverflow
Solution 2 - FlutterCollin JacksonView Answer on Stackoverflow
Solution 3 - FlutterCopsOnRoadView Answer on Stackoverflow
Solution 4 - FlutterchunhunghanView Answer on Stackoverflow
Solution 5 - FlutterbartektartanusView Answer on Stackoverflow
Solution 6 - FlutterSyed Ahsan AliView Answer on Stackoverflow
Solution 7 - FlutterVijay RamView Answer on Stackoverflow
Solution 8 - FlutterPierreView Answer on Stackoverflow
Solution 9 - FlutterFellipe SanchesView Answer on Stackoverflow
Solution 10 - FlutterhunterosView Answer on Stackoverflow
Solution 11 - FlutterGene BoView Answer on Stackoverflow