我想创建一个超链接显示在我的扑动应用程序。
超链接应该嵌入到Text或类似的文本视图中,例如:
Text
The last book bought is <a href='#'>this</a>
有什么提示吗?
Flutter没有内置的超链接支持,但您可以自己伪造它。在画廊drawer.dart中有一个例子。它们使用一个包含彩色TextSpan的RichText小部件,它有一个recognizer属性来处理点击:
TextSpan
RichText
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, ), ], ),
只需将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小部件和附带的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'); }, ), ], ), ), ), ), ); } }
这样你就可以突出显示一个单词,并从中创建一个超链接;)
如果你想让它看起来更像一个链接,你可以添加下划线:
new Text("Hello Flutter!", style: new TextStyle(color: Colors.blue, decoration: TextDecoration.underline),)
结果是:
打开info.plist文件并添加:
info.plist
<key>LSApplicationQueriesSchemes</key> <array> <string>https</string> </array>
打开位于app/src/main中的AndroidManifest.xml文件,并在根目录添加以下内容:
app/src/main
AndroidManifest.xml
<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>
简单地将你的Text包装在GestureDetector或InkWell中,并使用url_launcher包在onTap()中处理单击。
GestureDetector
InkWell
url_launcher
onTap()
InkWell( onTap: () => launchUrl(Uri.parse('https://www.google.com')), child: Text( 'Click here', style: TextStyle(decoration: TextDecoration.underline, color: Colors.blue), ), )
在应用中添加可点击链接的另一种(或不是)方法 (对我来说就是这样):
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'; } } }
可以使用flutter_linkify 包 https://pub.dev/packages/flutter_linkify < br > 只是想提供另一种选择。< br > 包将区分文本并自动突出显示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'; } } }
你可以使用链接文本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, ), ), ); }
在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, ), ), ); }, ),
这个问题的答案建议使用RichText和TextSpan + GestureRecognizer在功能上都是正确的,但从用户体验的角度来看,他们没有为响应触摸的用户提供反馈。为了保持与其他Material小部件的一致性,你可以使用类似的方法,但是使用WidgetSpan + InkWell。
GestureRecognizer
WidgetSpan
这个例子使用了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'; } } }
如果你想拥有更高级的文本功能,你可以使用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... }, )
这只是这个插件功能的冰山一角。
只是一个想法:你甚至可以把你的flutter应用程序的一部分作为html在线托管,并使用这个插件将它们渲染为flutter中的小部件。
child: LinkText( 'Hello check http://google.com', textStyle: ..., ),
对于这种复杂性,使用库更安全
优点:
再添加一个简单而整洁的技巧,因为上面的技巧对于某些用例来说过于复杂。我用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), ); } }