如何在Flutter小部件中创建超链接?

Tay*_*orR 55 flutter

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

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

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

任何提示这样做?

Rai*_*ann 76

只需在Text小部件周围包装InkWell,并将UrlLauncher(从服务库)提供给onTap属性:

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 InkWell(
              child: new Text('Open Browser'),
              onTap: () => launch('https://docs.flutter.io/flutter/services/UrlLauncher-class.html')
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以为"文本"窗口小部件提供样式,使其看起来像链接.

更新

在仔细研究这个问题之后,我找到了一个不同的解决方案来实现您要求的"在线"超链接.您可以将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');
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以实际突出显示一个单词并从中创建超链接;)

  • 您没有正确处理“TapGestureRecognizer”的生命周期。当不再使用“RichText”时,您必须调用“dispose()”方法。请参阅此处:https://api.flutter.dev/flutter/painting/TextSpan/recognizer.html (7认同)
  • UrlLauncher不再是扑动的一部分,它被移动到[插件和API更改](https://pub.dartlang.org/packages/url_launcher). (5认同)
  • 我们还需要添加导入:import'package:flutter / gestures.dart'; 导入'package:url_launcher / url_launcher.dart'; (4认同)
  • @CoreyCole `StatelessWidget` 不会神奇地为您处置您的 `TapGestureRecognizer`。事实上,在这种情况下使用 `StatelessWidget` 是不正确的,因为你不能以这种方式处理你的资源。是的,您绝对需要调用 TapGestureRecognizer 的 dispose() 方法,因为它运行需要停止的内部计时器。 (3认同)

Col*_*son 21

Flutter没有内置的超链接支持,但您可以自己伪造.在Gallery的drawer.dart中有一个例子.

超链接 浏览器

  • 这就是我链接到的示例的作用。我在答案中添加了一些图片来展示它。 (3认同)

chu*_*han 15

您可以使用 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';
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Cop*_*oad 13

你可以用你TextGestureDetector和手柄的点击中onTap()

GestureDetector(
  child: Text("Click here", style: TextStyle(decoration: TextDecoration.underline, color: Colors.blue)),
  onTap: () {
    // do what you need to do when "Click here" gets clicked
  }
)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  • @dmarquina 是的,您可以使用 `InkWell` 代替 `GestureDetector`。 (3认同)

Dee*_*shu 10

添加一个更简单和巧妙的技巧,因为上述技巧对于某些用例来说过于复杂。我使用 RichText - WidgetSpan、TextButton 和URL 启动器包完成此操作。只需根据您的需要修改下面的示例块即可。

结果:结果

代码:

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

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          child: RichText(
            textAlign: TextAlign.center,
            text: TextSpan(
              text: 'By logging in, you accept our ',
              style: Theme.of(context).textTheme.bodySmall,
              children: const <InlineSpan>[
                WidgetSpan(
                  alignment: PlaceholderAlignment.baseline,
                  baseline: TextBaseline.alphabetic,
                  child: LinkButton(
                      urlLabel: "Terms and Conditions",
                      url: "https://example.com/terms-and-conditions"),
                ),
                TextSpan(
                  text: ' and ',
                ),
                WidgetSpan(
                  alignment: PlaceholderAlignment.baseline,
                  baseline: TextBaseline.alphabetic,
                  child: LinkButton(
                      urlLabel: "Privacy Policy",
                      url: "https://example.com/privacy-policy"),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

link_button.dart

class LinkButton extends StatelessWidget {
  const LinkButton({Key? key, required this.urlLabel, required this.url})
      : super(key: key);

  final String urlLabel;
  final String url;

  Future<void> _launchUrl(String url) async {
    final Uri uri = Uri.parse(url);

    if (!await launchUrl(uri)) {
      throw 'Could not launch $uri';
    }
  }

  @override
  Widget build(BuildContext context) {
    return TextButton(
      style: TextButton.styleFrom(
        padding: EdgeInsets.zero,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(0),
        ),
        tapTargetSize: MaterialTapTargetSize.shrinkWrap,
        visualDensity: VisualDensity.compact,
        minimumSize: const Size(0, 0),
        textStyle: Theme.of(context).textTheme.bodySmall,
      ),
      onPressed: () {
        _launchUrl(url);
      },
      child: Text(urlLabel),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

注意:如果您收到与调用相关的错误launchUrl,请确保安装URL 启动程序包,然后重建您的应用程序。


小智 8

颤动链接小部件

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

url_launcher: ^6.0.8
Run Code Online (Sandbox Code Playgroud)

了解更多信息

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,
                ),
              ),
            );
          },
        ),
Run Code Online (Sandbox Code Playgroud)


bar*_*nus 7

如果您想使其看起来更像一个链接,则可以添加下划线:

new Text("Hello Flutter!", style: new TextStyle(color: Colors.blue, decoration: TextDecoration.underline),)
Run Code Online (Sandbox Code Playgroud)

结果:

在此处输入图片说明

  • 这不是问题的答案,而是对某人答案的评论。此外,按钮不是内嵌文本超链接。 (7认同)

Sye*_*Ali 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,
      ),
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)


Pie*_*rre 5

如果您想拥有更高级的文本功能,可以使用flutter_html插件:

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...
  },
)
Run Code Online (Sandbox Code Playgroud)

这只是该插件功能的冰山一角。

只是一个想法:您甚至可以将 flutter 应用程序的部分内容作为 html 在线托管,并使用此插件将它们作为小部件在 flutter 中渲染。