发布时间:2020年7月2日-9分钟阅读
Flutter InAppWebView.
什么是flutter_inappwebview ? 这是一个Flutter插件,它允许你将WebView小部件整合到你的Flutter应用中,使用无头WebViews,或者使用In-App浏览器。
那么,webview_flutter(官方flutter插件)和flutter_webview_plugin有什么区别呢?
与其他所有WebView插件相比,它的功能很丰富:有很多事件、方法和选项来控制WebViews。此外,他们并没有很好的关于他们的API的文档,或者说,至少是不完整的。相反,flutter_inappwebview
的每一个功能几乎都有文档可查(只要查看pub.dev上的API Reference)。
在这篇文章中,我将介绍人们在flutter_inappwebview官方仓库(issue部分)和StackOverflow上询问的InAppWebView
小部件的主要类和一些例子。
主类概述
这是一个插件提供的主要类的列表。
- InAppWebView: Flutter Widget,用于添加一个集成到flutter widget树中的内嵌式本地WebView。
- ContextMenu。该类表示WebView的上下文菜单。
- HeadlessInAppWebView。代表无头模式的WebView的类。它可以用来在后台运行WebView,而不需要将InAppWebView附加到widget树中。
- InAppBrowser:使用原生WebView的In-App浏览器。使用原生WebView的In-App浏览器。
- ChromeSafariBrowser:使用Chrome自定义标签的应用内浏览器。在Android上使用Chrome自定义标签/在iOS上使用SFSafariViewController的In-App浏览器。
- InAppLocalhostServer:该类允许你创建一个简单的应用程序浏览器,在Android上使用Chrome自定义标签,在iOS上使用SFSafariViewController。该类允许你在http://localhost:[port]/上创建一个简单的服务器。默认端口值为8080。
- CookieManager:该类实现了一个单人对象。该类实现了一个单人对象(共享实例),用于管理WebView实例使用的Cookie。
- HttpAuthCredentialDatabase。这个类实现了一个单人对象(共享实例),它管理共享的HTTP auth凭证缓存。
- WebStorageManager:该类实现了一个单人对象(共享实例),用于管理共享的HTTP authentials缓存。这个类实现了一个单子对象(共享实例),它管理WebView实例使用的Web存储。
在这篇文章中,我将特别展示InAppWebView
小部件,那是最常用/最需要的一个。
InAppWebView是一个和其他Widget一样的Widget!
将InAppWebView
小部件添加到你的应用程序中是非常简单的。它只是一个像任何其他Flutter小部件一样的小部件。InAppWebView(initialUrl: 'https://github.com/flutter')
。
注意:要在iOS上使用它,你需要通过在应用程序的Info.plist
文件中添加一个布尔属性来选择嵌入式视图预览,其键为io.flutter.embedded_views_preview
,值为YES。
这个widget有一组初始属性,你可以用它来初始化WebView。
- initialUrl: 将被加载的初始URL。
- initialOptions:将被加载的初始URL; initialOptions:将被使用的初始WebView选项。将要使用的初始WebView选项。
- gestureRecognizers:指定哪些手势应该被WebView消耗。
- initialData:初始InAppWebViewInitial数据。将要加载的InAppWebViewInitialData的初始数据,比如一个HTML字符串。
- initialFile:将被加载的初始资产文件(查看 "加载资产文件夹内的文件 "部分)。
- initialHeaders: 将要使用的初始头文件。将要使用的初始头文件。
- contextMenu:上下文菜单,包含自定义菜单项。上下文菜单,包含自定义菜单项。
所有可用的WebView选项列表相当长,例如,您可以使用javascriptEnabled
选项启用/禁用JavaScript,或使用cacheEnabled
选项启用/禁用缓存。所有选项的完整列表可以在这里找到。
使用InAppWebViewController来控制你的WebView。
相反,为了控制WebView,你有InAppWebViewController
类。当WebView准备好使用时,这个控制器由onWebViewCreated
回调返回。
通过它,你可以控制你的WebView或者访问它的属性,比如使用getUrl
方法访问当前的URL。其他方法,例如,loadUrl
加载一个新的URL,postUrl
使用POST方法加载一个给定的带有自定义数据的URL,evaluationJavascript
评估JavaScript代码到WebView中,并得到评估结果,takeScreenshot
拍摄WebView可见视口的截图(PNG格式),getCertificate
获取主顶层页面的SSL证书,如果没有证书则为null
。你可以使用的所有方法的完整列表相当长,可以在这里找到。
InAppWebView事件
InAppWebView
小部件提供了各种事件! 下面是其中的几个事件。
- onLoadStart:当WebView开始加载一个URL时被触发的事件。
- onLoadStop:当WebView完成加载一个URL时触发的事件。
- onLoadHttpError:当WebView主页面收到一个HTTP错误时被触发的事件。
- onConsoleMessage:当WebView收到JavaScript控制台消息(如
console.log
,console.error
等)时触发的事件。 - shouldOverrideUrlLoading:当当前WebView中的URL即将被加载时,给主机应用程序一个控制的机会。
- onDownloadStart:当WebView识别到一个可下载的文件时发射的事件。
- onReceivedHttpAuthRequest:当WebView接收到HTTP认证请求时触发的事件。默认行为是取消该请求。
- onReceivedServerTrustAuthRequest:当WebView需要执行服务器信任认证(证书验证)时被触发的事件。
- onPrint:当
window.print()
从JavaScript端被调用时被触发的事件,默认行为是取消请求;onCreateWindow:当WebView需要进行服务器信任验证(证书验证)时被触发的事件。 - onCreateWindow: 当InAppWebView请求主机应用程序创建一个新窗口时,例如当试图打开一个
target="_blank"
的链接或当window.open()
被JavaScript端调用时,事件被触发。
还有很多很多 我建议查看API参考资料来了解更多细节。至于WebView的选项和方法,所有WebView事件的完整列表相当长,可以在这里找到。
InAppWebView简单示例
这是一个简单的例子,显示了一个InAppWebView
小组件,它的当前URL和3个按钮:一个是返回,一个是前进,另一个是重新加载当前页面。
InAppWebView的例子。
这是完整的代码示例。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
InAppWebViewController _webViewController;
String url = "";
double progress = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('InAppWebView Example'),
),
body: Container(
child: Column(children: <Widget>[
Container(
padding: EdgeInsets.all(20.0),
child: Text(
"CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"),
),
Container(
padding: EdgeInsets.all(10.0),
child: progress < 1.0
? LinearProgressIndicator(value: progress)
: Container()),
Expanded(
child: Container(
margin: const EdgeInsets.all(10.0),
decoration:
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: InAppWebView(
initialUrl: "https://flutter.dev/",
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
)
),
onWebViewCreated: (InAppWebViewController controller) {
_webViewController = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
setState(() {
this.url = url;
});
},
onLoadStop: (InAppWebViewController controller, String url) async {
setState(() {
this.url = url;
});
},
onProgressChanged: (InAppWebViewController controller, int progress) {
setState(() {
this.progress = progress / 100;
});
},
),
),
),
ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Icon(Icons.arrow_back),
onPressed: () {
if (_webViewController != null) {
_webViewController.goBack();
}
},
),
RaisedButton(
child: Icon(Icons.arrow_forward),
onPressed: () {
if (_webViewController != null) {
_webViewController.goForward();
}
},
),
RaisedButton(
child: Icon(Icons.refresh),
onPressed: () {
if (_webViewController != null) {
_webViewController.reload();
}
},
),
],
),
])),
),
);
}
}
JavaScript处理程序(通道)
你可以和JavaScript端进行通信,反之亦然。要添加一个JavaScript处理程序,可以使用_webViewController.addJavaScriptHandler
方法,在该方法中定义了handlerName
和一个callback
,当它被JavaScript端调用时,就会被调用。回调可以返回JavaScript端要发送的数据。
而在JavaScript端,要执行回调处理程序并向Flutter发送数据,则需要使用window.flutter_inappwebview.callHandler(handlerName <String>,...args)
方法,其中handlerName
是一个字符串,代表你调用的处理程序名称,args是你可以向Flutter端发送的可选参数。
为了正确调用window.flutter_inappwebview.callHandler(handlerName <String>, ...args)
,你需要等待并监听JavaScript事件flutterInAppWebViewPlatformReady
。一旦平台(Android或iOS)准备好处理callHandler
方法,这个事件就会被派发。
下面是一个例子。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
InAppWebViewController _webViewController;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('InAppWebView Example'),
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child:InAppWebView(
initialData: InAppWebViewInitialData(
data: """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
</head>
<body>
<h1>JavaScript Handlers (Channels) TEST</h1>
<script>
window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
window.flutter_inappwebview.callHandler('handlerFoo')
.then(function(result) {
// print to the console the data coming
// from the Flutter side.
console.log(JSON.stringify(result));
window.flutter_inappwebview
.callHandler('handlerFooWithArgs', 1, true, ['bar', 5], {foo: 'baz'}, result);
});
});
</script>
</body>
</html>
"""
),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
)
),
onWebViewCreated: (InAppWebViewController controller) {
_webViewController = controller;
_webViewController.addJavaScriptHandler(handlerName:'handlerFoo', callback: (args) {
// return data to JavaScript side!
return {
'bar': 'bar_value', 'baz': 'baz_value'
};
});
_webViewController.addJavaScriptHandler(handlerName: 'handlerFooWithArgs', callback: (args) {
print(args);
// it will print: [1, true, [bar, 5], {foo: baz}, {bar: bar_value, baz: baz_value}]
});
},
onConsoleMessage: (controller, consoleMessage) {
print(consoleMessage);
// it will print: {message: {"bar":"bar_value","baz":"baz_value"}, messageLevel: 1}
},
),
),
])),
),
);
}
}
InAppWebView中的WebRTC
目前,WebRTC只在Android上支持,因为不幸的是,在iOS上WKWebView并没有实现所有的WebRTC API(你可以关注这个问题:#200)。
我将使用appr.tc/ 来展示一个测试WebRTC功能的例子。这是一个基于WebRTC的视频聊天演示应用(github.com/webrtc/appr…
要请求关于摄像头和麦克风的权限,你可以使用 permission_handler 插件。另外,你需要将WebView选项mediaPlaybackRequiresUserGesture
设置为false
,才能自动播放HTML5音频和视频。
此外,在Android上,你需要实现androidOnPermissionRequest
事件(这是一个Android特有的事件),也就是当WebView请求访问特定资源的权限时,会被触发的事件(也就是Android原生WebChromeClient.onPermissionRequest事件)。在这种情况下,该事件用于授予WebRTC API的权限。此外,你还需要在AndroidManifest.xml
中添加这些权限。
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.VIDEO_CAPTURE" />
<uses-permission android:name="android.permission.AUDIO_CAPTURE" />
WebRTC的例子。
下面是完整的代码示例。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:permission_handler/permission_handler.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Permission.camera.request();
await Permission.microphone.request();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: InAppWebViewPage()
);
}
}
class InAppWebViewPage extends StatefulWidget {
@override
_InAppWebViewPageState createState() => new _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
InAppWebViewController _webViewController;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("InAppWebView")
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: "https://appr.tc/r/704328056",
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
mediaPlaybackRequiresUserGesture: false,
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
_webViewController = controller;
},
androidOnPermissionRequest: (InAppWebViewController controller, String origin, List<String> resources) async {
return PermissionRequestResponse(resources: resources, action: PermissionRequestResponseAction.GRANT);
}
),
),
),
]))
);
}
}
如何在InAppWebView中启用下载文件的功能
InAppWebView
可以识别Android和iOS平台上的可下载文件。为了能够识别可下载文件,你需要设置useOnDownloadStart: true
选项,然后你就可以监听onDownloadStart
事件。
在Android平台上,你需要在你的AndroidManifest.xml
文件里面添加写权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
然后,你需要使用 permission_handler 插件询问权限。相反,为了有效下载你的文件,你可以使用flutter_downloader插件。
这里是一个完整的例子,使用ovh.net/files/(特别是h… 作为URL)来测试下载。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await FlutterDownloader.initialize(
debug: true // optional: set false to disable printing logs to console
);
await Permission.storage.request();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
InAppWebViewController _webViewController;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('InAppWebView Example'),
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: InAppWebView(
initialUrl: "http://ovh.net/files/1Mio.dat",
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
useOnDownloadStart: true
),
),
onWebViewCreated: (InAppWebViewController controller) {
_webViewController = controller;
},
onDownloadStart: (controller, url) async {
print("onDownloadStart $url");
final taskId = await FlutterDownloader.enqueue(
url: url,
savedDir: (await getExternalStorageDirectory()).path,
showNotification: true, // show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);
},
))
])),
),
);
}
}
正如你所看到的,我也使用path_provider插件来获取我想保存文件的文件夹。
允许使用自签名的SSL证书
要允许自签名的SSL证书,你可以使用onReceivedServerTrustAuthRequest
事件,然后简单地返回继续请求。
onReceivedServerTrustAuthRequest: (controller, challenge) async {
return ServerTrustAuthResponse(action: ServerTrustAuthResponseAction.PROCEED);
},
如何管理用target="_blank "或 "window.open "打开的弹出窗口。
当用户点击target="_blank "
的链接或通过使用window.open
的JavaScript代码来管理弹出窗口时,你可以使用onCreateWindow
事件。在Android上,为了能够允许这个事件,你需要将supportMultipleWindows
选项设置为true。另外,为了能够允许使用JavaScript,你需要将javaScriptCanOpenWindowsAutomatically
设置为true。
如果你想管理这些请求,你应该从这个事件中返回true
,否则,这个事件的默认实现什么也不做,因此返回false
。
CreateWindowRequest
代表导航请求,它包含一个windowId
,可以用来创建,例如,一个新的InAppWebView
实例。这个windowId
被本地代码用来映射该请求和用于管理该请求的WebView。
另外,CreateWindowRequest
包含了请求的url
(在Android上,如果弹出窗口是用window.open
的JavaScript打开的,它将是null
),但是如果你需要维护Window
JavaScript对象引用(用window.open
方法创建的),例如,调用window.close
方法,那么你应该用windowId
创建新的WebView,而不使用url。
下面是一个简单的例子,当用户点击链接时,会显示一个AlertDialog
。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: InAppWebViewPage()
);
}
}
class InAppWebViewPage extends StatefulWidget {
@override
_InAppWebViewPageState createState() => new _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
InAppWebViewController _webViewController;
InAppWebViewController _webViewPopupController;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('InAppWebView Example'),
),
body: SafeArea(
child: Container(
child: InAppWebView(
initialData: InAppWebViewInitialData(
data: """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Flutter InAppWebView</title>
</head>
<body>
<a style="margin: 50px; background: #333; color: #fff; font-weight: bold; font-size: 20px; padding: 15px; display: block;"
href="https://github.com/flutter"
target="_blank">
Click here to open https://github.com/flutter in a popup!
</a>
</body>
</html>
"""
),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
// set this to true if you are using window.open to open a new window with JavaScript
javaScriptCanOpenWindowsAutomatically: true
),
android: AndroidInAppWebViewOptions(
// on Android you need to set supportMultipleWindows to true,
// otherwise the onCreateWindow event won't be called
supportMultipleWindows: true
)
),
onWebViewCreated: (InAppWebViewController controller) {
_webViewController = controller;
},
onCreateWindow: (controller, createWindowRequest) async {
print("onCreateWindow");
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Container(
width: MediaQuery.of(context).size.width,
height: 400,
child: InAppWebView(
// Setting the windowId property is important here!
windowId: createWindowRequest.windowId,
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
_webViewPopupController = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
print("onLoadStart popup $url");
},
onLoadStop: (InAppWebViewController controller, String url) {
print("onLoadStop popup $url");
},
),
),
);
},
);
return true;
},
),
),
),
),
);
}
}
onCreateWindow事件 - 弹出窗口示例。
管理平台URL,如whatsapp:、fb:、tel:、mailto:等。
一般情况下,WebView不知道如何管理whatsapp:
,tel:
或fb:
协议/scheme: ,tel:或fb:协议/scheme。为了捕获这些自定义协议/scheme的请求,你可以使用shouldOverrideUrlLoading
事件(你需要用useShouldOverrideUrlLoading: true
选项启用它)。
这样你就可以取消对WebView的请求,而是打开App,例如,使用url_launcher
插件。
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
useShouldOverrideUrlLoading: true
),
),
shouldOverrideUrlLoading: (controller, request) async {
var url = request.url;
var uri = Uri.parse(url);
if (!["http", "https", "file",
"chrome", "data", "javascript",
"about"].contains(uri.scheme)) {
if (await canLaunch(url)) {
// Launch the App
await launch(
url,
);
// and cancel the request
return ShouldOverrideUrlLoadingAction.CANCEL;
}
}
return ShouldOverrideUrlLoadingAction.ALLOW;
},
管理WebView Cookies
要管理WebView cookie,可以使用CookieManager类,它实现了一个单人对象(共享实例)。在 Android 上,它是使用 CookieManager 类实现的。在iOS上,它是使用WKHTTPCookieStore类实现的。
下面是一个如何设置cookie的例子。
CookieManager _cookieManager = CookieManager.instance();
final expiresDate =
DateTime.now().add(Duration(days: 3)).millisecondsSinceEpoch;
_cookieManager.setCookie(
url: "https://flutter.dev/",
name: "session",
value: "54th5hfdcfg34",
domain: ".flutter.dev",
expiresDate: expiresDate,
isSecure: true,
);
自定义上下文菜单
您可以自定义WebView的上下文菜单,添加自定义菜单项,和/或隐藏默认的系统菜单项。对于每个自定义菜单项,你可以声明一个回调action
,当用户点击它时,就会被调用。举个例子,我将添加一个名为Special
的自定义菜单项,并定义一个回调动作,在用户选择文本时向用户显示一个JavaScript window.alert
。
自定义菜单项的例子。
这里是完整的代码示例。
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: InAppWebViewPage()
);
}
}
class InAppWebViewPage extends StatefulWidget {
@override
_InAppWebViewPageState createState() => new _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
InAppWebViewController _webViewController;
ContextMenu contextMenu;
@override
void initState() {
super.initState();
contextMenu = ContextMenu(
menuItems: [
ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async {
print("Menu item Special clicked!");
var selectedText = await _webViewController.getSelectedText();
await _webViewController.clearFocus();
await _webViewController.evaluateJavascript(source: "window.alert('You have selected: $selectedText')");
})
],
options: ContextMenuOptions(
hideDefaultSystemContextMenuItems: false
),
onCreateContextMenu: (hitTestResult) async {
print("onCreateContextMenu");
print(hitTestResult.extra);
print(await _webViewController.getSelectedText());
},
onHideContextMenu: () {
print("onHideContextMenu");
},
onContextMenuActionItemClicked: (contextMenuItemClicked) async {
var id = (Platform.isAndroid) ? contextMenuItemClicked.androidId : contextMenuItemClicked.iosId;
print("onContextMenuActionItemClicked: " + id.toString() + " " + contextMenuItemClicked.title);
}
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("InAppWebView")
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: "https://github.com/flutter",
contextMenu: contextMenu,
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
_webViewController = controller;
},
),
),
),
]))
);
}
}
结束语
在这篇文章中,我对flutter_inappwebview插件做了一点介绍,特别是关于InAppWebView
小部件的介绍。这个插件正在持续开发中(在写这篇文章的时候,最新的版本是4.0.0
),我建议你查看API Reference来了解所有的功能。对于任何新的功能请求/bug修复,你可以使用版本库的问题部分。
下一篇文章将介绍如何使用这个插件实现一个全功能浏览器:在Flutter中使用WebViews创建一个全功能浏览器。
今天的内容就到这里了! 希望它为你的Flutter应用打开了新的用例。
通过www.DeepL.com/Translator(免费版)翻译