webview_win_floating
Windows / Linux 向けの WebView。package webview_flutter のインターフェースを実装する Flutter プラグイン。
Windows / Linux 向けの Flutter WebView。webview_flutter のインターフェースを実装するプラグインでもあります。
{"sdk":"flutter"}^2.1.0^2.13.0^1.0.4{"sdk":"flutter"}—以下は英語原文のスナップショットです。最新版は GitHub をご覧ください。
A desktop Flutter WebView plugin for Windows and Linux.
It exposes the same API as webview_flutter, so you can reuse familiar WebView code while targeting desktop platforms.
For developers upgrading from version 2.x to 3.x, please refer to API BREAKING CHANGES
https://raw.githubusercontent.com/jakky1/webview_win_floating/master/screenshot.jpg
| Platform | Support | Use Library |
|---|---|---|
| Windows | ✅ | WebView2 |
| Linux | ✅ | webkit2gtk-4.1 |
You can write your app against the webview_flutter API and use this package as the desktop implementation.
This package places a native WebView directly on top of the Flutter window instead of rendering it as a texture.
That design has a tradeoff:
Hmm... there are so many limitations.
If your application targets only Windows or Linux, refer to the [Standalone mode] section below and use controller.setVisibility(bool) to toggle the WebView visibility.
Use this package if:
Linux has a few build-time considerations. See README_Linux.md for details.
Add the package to your pubspec.yaml:
dependencies:
webview_win_floating: ^3.0.0
webview_flutter: ^4.13.0
NOTE: all the interface are supplied by webview_flutter
final controller = WebViewController();
@override
void initState() {
super.initState();
controller.setJavaScriptMode(JavaScriptMode.unrestricted);
controller.loadRequest(Uri.parse("https://www.google.com/"));
}
@override
Widget build(BuildContext context) {
return WebViewWidget(controller: controller);
}
Enable JavaScript before loading pages that need it:
controller.setJavaScriptMode(JavaScriptMode.unrestricted);
For example, to disable the facebook / twitter links in youtube website:
controller.setNavigationDelegate(NavigationDelegate(
onNavigationRequest: (request) {
return request.url.contains("youtube")
? NavigationDecision.navigate
: NavigationDecision.prevent;
},
));
Hint: you can rename the name 'myChannelName' in the following code
controller.addJavaScriptChannel("myChannelName",
onMessageReceived: (JavaScriptMessage jmsg) {
String message = jmsg.message;
print(message); // print "This message is from javascript"
}
);
controller.loadHtmlString(htmlContent);
controller.runJavascript("callByDart(100)");
var htmlContent = '''
<html>
<body>
<script>
function callByDart(int value) {
console.log("callByDart: " + value);
}
myChannelName.postMessage("This message is from javascript");
</script>
</body>
</html>
''';
Supported callbacks include:
controller.setNavigationDelegate(NavigationDelegate(
onPageStarted: (url) {
print("onPageStarted: $url");
},
onPageFinished: (url) {
print("onPageFinished: $url");
},
onUrlChange: (change) {
String url = change.url ?? "";
print("onUrlChange: $url"),
},
onHttpError: (error) {
int httpCode = error.response!.statusCode; // e.g. 403 (Not Found)
String url = error.response!.uri.toString();
print("onHttpError: code=$httpCode, url : $url");
},
onSslAuthError: (error) {
if (error is WinSslAuthError) {
print("onSslAuthError: ${(error as WinSslAuthError).url}");
} else {
print("onSslAuthError: unknown url}");
}
error.cancel();
},
onWebResourceError: (error) {
print("onWebResourceError: ${error.url} => ${error.description}");
},
));
controller = null;
// and make sure no any WebViewWidget keep that controller object.
After official API interface webview_flutter: 4.0.0, controller is disposed after the WebViewController object is garbage collected.
So the controller object may not be disposed immediately when no any pointer keep the controller object.
Some websites request permissions such as notifications or camera access.
If you do not provide onPermissionRequest, all permission requests are denied by default.
For example, you can test Notification permission with the following code, in this site
final controller = WebViewController(onPermissionRequest: (request) {
if (Platform.isWindows) {
var req = request.platform as WinWebViewPermissionRequest;
print("permission: ${req.kind} , ${req.url}");
// only allow "notification", deny all others
if (req.kind == WinWebViewPermissionResourceType.notification) {
req.grant();
} else {
req.deny();
}
}
});
If onPermissionRequest is not provided, all the permission requests will be denied automatically:
final controller = WebViewController();
Diffrent platforms have different implementations. Windows WebView2 allow you to grant/deny the following permission types:
enum WinWebViewPermissionResourceType {
unknown,
microphone,
camera,
geoLocation,
notification,
otherSensors,
clipboardRead
}
User Data Folder:
C:\Program Files\, set a custom user data folder.Profiles:
<UserDataFolder>/EBWebView/WV2Profile_<ProfileName>/String cacheDir = "c:\\test";
String profileName = "UserA";
var params = WindowsWebViewControllerCreationParams(userDataFolder: cacheDir, profileName: profileName);
var controller = WebViewController.fromPlatformCreationParams(params);
If your application build with InnoSetup, or can be installed in "C:/Program Files/" or other read-only system directory, the webview cannot create data folder in read-only directory, so it won't work.
In this case, you should specify user data folder as mentioned above.
If your app only targets Windows and you want fewer dependencies, you can remove the webview_flutter dependency:
dependencies:
webview_win_floating: ^3.0.0
# webview_flutter: ^4.13.0 # mark this line for Windows only app
Then rename the core classes:
WebViewWidget -> WinWebViewWidget // add "Win" prefix
WebViewController -> WinWebViewController // add "Win" prefix
NavigationDelegate -> WinNavigationDelegate // add "Win" prefix
just only modify class names. All the properties / method are the same with webview_flutter
For permission grant/deny:
final controller = WinWebViewController(onPermissionRequest: (req) {
print("permission: ${req.kind} , ${req.url}");
// only allow "notification", deny all others
if (req.kind == WinWebViewPermissionResourceType.notification) {
req.grant();
} else {
req.deny();
}
});
The standalone Windows API also includes:
final controller = WinWebViewController();
controller.setVisibility(false); // hide webview
Additional information:
With the information above, you can manually trigger WebView visibility by hooking into navigator.push / pop events or widget visibility changes.
If your build fails with an error containing MSB3073, run the build command from an Administrator terminal.
If you use history.back() in JavaScript, remove your NavigationDelegate.onNavigationRequest() implementation. That callback can interfere with back navigation.
import 'package:flutter/material.dart';
import 'package:webview_win_floating/webview_win_floating.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final controller = WebViewController();
@override
void initState() {
super.initState();
controller.setJavaScriptMode(JavaScriptMode.unrestricted);
controller.loadRequest(Uri.parse("https://www.google.com/"));
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Windows Webview example app'),
),
body: WebViewWidget(controller: controller),
),
);
}
}