我想创建一个超链接显示在我的扑动应用程序。

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

最近买的一本书是<a href='#'>this</a>

有什么提示吗?


当前回答

对于这个问题的答案,建议使用RichText和TextSpan + GestureRecognizer在功能上都是正确的,但从用户体验的角度来看,他们不提供反馈给用户响应触摸。为了保持与其他Material小部件的一致性,您可以使用类似的方法,但是使用WidgetSpan + InkWell代替。

这个例子使用了url_launcher包和一个非样式的InkWell,但是你可以自定义你认为合适的:

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

其他回答

这是一整套的钥匙 https://pub.dev/packages/link_text

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

对于这种复杂性,使用库更安全

优点:

作为单个参数接受整个字符串 解析链接并将其呈现为可点击的UI,与不可点击的文本内联 不需要复杂的RichText结构

在你的应用中添加可点击链接的另一种(或不是)方式(对我来说就是这样):

1 -在你的pubspec中添加url_launcher包。yaml文件

(包版本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';
    }
  }
}

更新(Android >= 11):

iOS configuration: Open info.plist file and add: <key>LSApplicationQueriesSchemes</key> <array> <string>https</string> </array> Android configuration: Open AndroidManifest.xml file located in app/src/main and add the following at the root: <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Add this query --> <queries> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="https" /> </intent> </queries> <application ... /> </manifest>

颤振代码:

简单地包装你的文本在一个手势探测器或InkWell和处理点击在onTap()使用url_launcher包。

InkWell(
  onTap: () => launchUrl(Uri.parse('https://www.google.com')),
  child: Text(
    'Click here',
    style: TextStyle(decoration: TextDecoration.underline, color: Colors.blue),
  ),
)

截图:

再添加一个简单而整洁的技巧,因为上面的技巧对于某些用例来说过于复杂。我用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"),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

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

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

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

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

结果是: