【问题标题】:How to create a hyperlink in Flutter widget?如何在 Flutter 小部件中创建超链接?
【发布时间】:2017-09-20 20:36:44
【问题描述】:

我想创建一个超链接以显示在我的 Flutter 应用程序中。

超链接应嵌入Text 或类似的文本视图中,例如:

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

有什么提示吗?

【问题讨论】:

标签: flutter


【解决方案1】:

只需将 InkWell 包裹在 Text 小部件周围,然后将 UrlLauncher(来自服务库)提供给 onTap 属性。在下面使用之前将UrlLauncher 安装为 Flutter 包。

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

您可以为 Text 小部件提供一种样式,使其看起来像一个链接。

更新

在稍微研究了这个问题后,我发现了一个不同的解决方案来实现您要求的“在线”超链接。您可以使用RichText Widget 和封闭的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');
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

这样您实际上可以突出显示一个单词并从中创建一个超链接;)

【讨论】:

  • UrlLauncher 不再是 Flutter 的一部分,它已移至 a plugin and API changed
  • 另外我们需要添加导入:import 'package:flutter/gestures.dart';导入'package:url_launcher/url_launcher.dart';
  • 您没有正确处理TapGestureRecognizer 的生命周期。当不再使用RichText 时,您必须调用dispose() 方法。见这里:api.flutter.dev/flutter/painting/TextSpan/recognizer.html
  • @AlexSemeniuk 在您的示例中,他们使用的是 StatefulWidget,在上面的答案中它是 StatelessWidget。确定要处理 StatelessWidget 的情况吗?
  • @CoreyCole StatelessWidget 不会神奇地为您处理您的TapGestureRecognizer。事实上,在这种情况下使用StatelessWidget 是不正确的,因为您不能以这种方式处理您的资源。是的,您绝对需要调用TapGestureRecognizerdispose() 方法,因为它运行需要停止的内部计时器。
【解决方案2】:

Flutter 没有内置的超链接支持,但你可以自己伪造它。 Gallery's drawer.dart 中有一个例子。他们使用包含有颜色的TextSpanRichText 小部件,它有一个recognizer 属性来处理点击:

        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,
              ),
            ],
          ),

【讨论】:

  • 谢谢。但这并不是我真正想要的东西:我正在寻找应用内导航之外的东西。
  • 我不确定您所说的“超越应用内导航”是什么意思。你想让链接打开浏览器吗?
  • 是的,可以点击链接或类似的东西在浏览器中打开。
  • 这就是我链接到的示例所做的。我在答案中添加了一些图片以显示它。
  • 回购链接已损坏
【解决方案3】:

您可以将您的Text 包装在GestureDetectorInkWell 中并处理onTap() 中的点击。如果你想启动一个url,你可以使用url_launcher包。

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

【讨论】:

  • 你是对的,你的解决方案的行数比其他解决方案少,但是 Inkwell 是这个特定工作的小部件,所以至少在语义上我认为这是最好的解决方案
  • @dmarquina 是的,您可以使用InkWell 代替GestureDetector
【解决方案4】:

你可以使用 package flutter_linkify
https://pub.dev/packages/flutter_linkify
只是想提供另一种选择。
包将自动划分您的文本并突出显示 http/https
结合插件 url_launcher 你可以启动 url
您可以查看以下示例:

完整代码如下

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: example@gmail.com \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';
    }
  }
}

【讨论】:

  • 如何在同一个小部件上有 2 个链接?例如,“单击此按钮即表示您接受使用条款和隐私政策”,我们需要将它们放在一起
  • 很棒的包。节省大量样板代码
  • @Dani 您可以根据需要添加任意数量的链接,因为颤振的 linkify 包对待每个链接都不同。我已经为超过 1 个链接测试了上面的 sn-p 并且它工作得很好
  • 谢谢。这就是我一直在寻找的
【解决方案5】:

如果你想让它看起来更像一个链接,你可以添加下划线:

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

结果:

【讨论】:

  • 不可点击!
  • 然后用 Button 小部件将其包裹起来。 :)
  • 这不是问题的答案,而是对某人答案的评论。按钮也不是内联文本超链接。
【解决方案6】:

在 Flutter 2.0 中,引入了 Link 小部件。使用此小部件启动网页并导航到应用程序中的新屏幕。使用前需要先使用 url_launcher 包。

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

【讨论】:

    【解决方案7】:

    您可以使用链接文本https://pub.dev/packages/link_text 并像使用它

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

    【讨论】:

    • 在 Linux 下 flutter pub get 因为它失败了 Unable to find a plugin.vcxproj for plugin "url_launcher_windows"
    • 这仅限于使链接可点击。不是一个字,指向一个链接
    【解决方案8】:

    另一种(或不)在您的应用中放置可点击链接的方法 (对我来说就是这样):

    1 - 在 pubspec.yaml 文件中添加 url_launcher 包

    (5.0的包对我来说不太好用,所以我用的是4.2.0+3)。

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

    2 - 如下导入并使用。

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

    【讨论】:

    • 如果需要一些文本之间的超链接,您可以使用FlatButton,其背景和文本颜色与其余文本相同,因此使用 TextDecoration.underline 对其进行格式化,如上图所示。 .
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    • 2019-12-27
    • 1970-01-01
    相关资源
    最近更新 更多