【发布时间】:2017-09-20 20:36:44
【问题描述】:
我想创建一个超链接以显示在我的 Flutter 应用程序中。
超链接应嵌入Text 或类似的文本视图中,例如:
The last book bought is <a href='#'>this</a>
有什么提示吗?
【问题讨论】:
标签: flutter
我想创建一个超链接以显示在我的 Flutter 应用程序中。
超链接应嵌入Text 或类似的文本视图中,例如:
The last book bought is <a href='#'>this</a>
有什么提示吗?
【问题讨论】:
标签: flutter
只需将 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');
},
),
],
),
),
),
),
);
}
}
这样您实际上可以突出显示一个单词并从中创建一个超链接;)
【讨论】:
TapGestureRecognizer 的生命周期。当不再使用RichText 时,您必须调用dispose() 方法。见这里:api.flutter.dev/flutter/painting/TextSpan/recognizer.html
StatelessWidget 不会神奇地为您处理您的TapGestureRecognizer。事实上,在这种情况下使用StatelessWidget 是不正确的,因为您不能以这种方式处理您的资源。是的,您绝对需要调用TapGestureRecognizer 的dispose() 方法,因为它运行需要停止的内部计时器。
Flutter 没有内置的超链接支持,但你可以自己伪造它。 Gallery's drawer.dart 中有一个例子。他们使用包含有颜色的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,
),
],
),
【讨论】:
您可以将您的Text 包装在GestureDetector 或InkWell 中并处理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 代替GestureDetector。
你可以使用 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';
}
}
}
【讨论】:
在 Flutter 2.0 中,引入了 Link 小部件。使用此小部件启动网页并导航到应用程序中的新屏幕。使用前需要先使用 url_launcher 包。
url_launcher: ^6.0.8
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,
),
),
);
},
),
【讨论】:
您可以使用链接文本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 pub get 因为它失败了 Unable to find a plugin.vcxproj for plugin "url_launcher_windows"
另一种(或不)在您的应用中放置可点击链接的方法 (对我来说就是这样):
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 对其进行格式化,如上图所示。 .