webview_plus 0.1.0
webview_plus: ^0.1.0 copied to clipboard
A cross-platform Flutter plugin that directly encapsulates native WebViews (Android WebView, iOS/macOS WKWebView, Windows WebView2, Linux WebKitGTK, Web iframe) with no third-party WebView dependencies.
webview_plus #
A high-performance, cross-platform Flutter plugin that directly encapsulates native Webview components on all supported platforms.
Unlike other webview implementations that introduce complex virtualization layers, webview_plus embeds the underlying platform's native web view directly for maximum speed, memory efficiency, and standard compliance.
🚀 Platform Support Matrix #
| Platform | Encapsulated Native Component | Backend Layer / Architecture |
|---|---|---|
| Android | android.webkit.Webview |
Native PlatformView (with Hybrid Composition support) |
| iOS | WKWebview (WebKit) |
Native UiKitView (Full native composition) |
| macOS | WKWebview (WebKit) |
Native AppKitView (Full native composition) |
| Windows | Webview2 (Edge Chromium) |
Win32 Composition over Flutter Direct3D Texture |
| Linux | WebKitWebview (WebKitGTK) |
Direct GtkWidget window overlay anchoring |
| Web | Native DOM <iframe> |
Standard HTML5 Element Embedding |
✨ Features #
- True Native Embedding: Zero unnecessary wrappers. Uses
WKWebviewon Apple platforms, Chromium-basedWebview2on Windows, andWebKitGTKon Linux. - Bi-directional JavaScript Bridge:
- Execute Dart to JS via
evaluateJavaScriptwith automatic type unboxing (returns real Dart types likeint,Map,Listinstead of raw strings). - Handle JS to Dart messages using either basic string streaming or full-featured promises via
window.webview_plus.callHandler.
- Execute Dart to JS via
- Custom Native Context Menus: Fully customize text selection and long-press contextual menus on Android and iOS using native platform APIs (
ActionMode&UIContextMenuConfiguration). - Comprehensive Lifecycle Callbacks: Track page loading starts, stops, navigation interception, and handle platform-specific web view errors.
- Advanced Asset & File System Access: Load URLs, bundle assets, or absolute file paths from the local device storage.
🛠️ Quick Start #
import 'package:flutter/material.dart';
import 'package:webview_plus/webview_plus.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Webview Plus Example')),
body: WebviewWidget(
initialAsset: 'assets/index.html',
onWebviewCreated: (controller) {
print("Webview has been successfully instantiated.");
},
onMessageReceived: (message) {
print("Received simple message from JS: $message");
},
onNavigationRequest: (url) {
// Block specific navigation paths
if (url.contains('blocked.com')) {
print("Navigation to $url blocked!");
return false; // Prevent navigation
}
return true; // Allow navigation
},
),
),
);
}
}
📖 Deep Dive & Advanced Usage #
1. Bi-directional JavaScript Interaction #
Dart to JavaScript (with Native Types)
Forget manual JSON parsing. When evaluating JavaScript, the native bridge deserializes data into native Dart objects directly.
// Evaluate arithmetic or complex data structures
final dynamic result = await controller.evaluateJavaScript('1 + 1');
print(result); // Outputs: 2 (as an int, not a String "2"!)
final Map<String, dynamic> user = await controller.evaluateJavaScript('''
(function() {
return { name: "Noam", roles: ["admin", "developer"] };
})()
''');
JavaScript to Dart Handlers (Promises & Callbacks)
Register namespaced handlers in Dart that return values or asynchronous futures directly back to JavaScript as native JS Promises.
Dart Implementation:
controller.addJavaScriptHandler(
handlerName: 'calculateTax',
callback: (args) async {
// args maps exactly to parameters passed from JS
double subtotal = args[0];
double rate = args[1];
return subtotal * rate; // Returned directly to JavaScript
},
);
JavaScript Call:
// window.webview_plus is automatically injected into the page context
window.webview_plus.callHandler('calculateTax', 100.0, 0.20)
.then(function(taxResult) {
console.log("Tax computed by Dart: " + taxResult); // 20
})
.catch(function(error) {
console.error("Error from Dart execution: ", error);
});
2. Custom Native Context Menus (Android & iOS) #
You can strip down or add custom buttons to the native text selection action bar. This is handled deep within native platform architectures (ActionMode on Android and UIContextMenuConfiguration on iOS).
WebviewPlus(
initialUrl: 'https://flutter.dev',
contextMenuItems: [
ContextMenuItem(
id: 'search_lookup',
name: 'Custom Lookup',
action: (selectedText) {
print("User highlighted and clicked lookup for: $selectedText");
},
),
],
initialSettings: const WebviewSettings(
// Disable standard copy/cut/paste items if necessary
disabledDefaultContextMenuItems: {
DefaultContextMenuItem.cut,
DefaultContextMenuItem.share, // If defined
},
),
)
Note: Context menu customizations are silently ignored on desktop platforms (Windows, macOS, Linux) where traditional right-click drop-down menus operate without touch-selection bars.
3. Detailed Controller API Reference #
The WebviewPlusController exposes full programmatic control over the browser session:
| Method | Description |
|---|---|
loadUrl(String url) |
Navigates to a remote or local URL (http://, https://, file://). |
loadFlutterAsset(String assetPath) |
Loads an HTML file bundled inside your Flutter application asset directory. |
loadFile(String filePath) |
Absolute filesystem lookup. Loads local files on the device disk. |
loadHtmlString(String html, {String? baseUrl}) |
Loads a raw HTML string into the webview component directly. |
loadData(...) |
Advanced alternative to loadHtmlString supporting explicit custom mimeType (e.g. image/svg+xml) and encoding. |
evaluateJavaScript(String code) |
Runs arbitrary JS in the document scope and retrieves automatically unboxed Dart objects. |
getHtml() |
Helper that queries and returns document.documentElement.outerHTML. |
injectJavascriptFileFromUrl / Asset |
Injects an external or asset-based <script> file straight into the live DOM tree. |
injectCSSFileFromUrl / Asset |
Appends remote stylesheets or asset-based CSS rules into the live DOM layout. |
goBack() / goForward() |
Navigates backwards or forwards through the session browsing history stack. |
canGoBack() / canGoForward() |
Evaluates whether historical steps are available in either direction. |
reload() |
Triggers a fresh reload of the current active webpage structure. |
⚙️ Configuration Options (WebviewSettings) #
Pass a custom WebviewSettings configuration object to fully customize behavior per-platform:
const WebviewSettings(
javaScriptEnabled: true,
domStorageEnabled: true,
transparentBackground: true,
isInspectable: true, // Enables Chrome DevTools / Safari Web Inspector debugging
)
Full Settings Parameter Grid #
| Property | Default | Platform | Scope / Behavior Description |
|---|---|---|---|
javaScriptEnabled |
true |
All | Controls JavaScript runtime execution. |
domStorageEnabled |
true |
Mobile/macOS | Enables localStorage, sessionStorage, and IndexedDB. |
allowFileAccess |
true |
Android | Permits explicit file scheme loads (file://). |
allowContentAccess |
true |
Android | Permits native Content Provider paths (content://). |
supportZoom |
true |
All | Determines if pinch-to-zoom gestures are captured. |
builtInZoomControls |
true |
Android | Displays default Android platform zoom utility components. |
displayZoomControls |
false |
Android | Overlays physical zoom buttons directly inside screen layout. |
mediaPlaybackRequiresUserGesture |
true |
All | Prevents HTML5 videos/media from autoplaying without user clicks. |
transparentBackground |
false |
All | Makes the viewport background transparent to display Flutter widgets behind. |
userAgent |
null |
All | Override target browser layout engine header. null falls back to system default. |
isInspectable |
false |
All | Opens hooks for Safari Web Inspector or Chrome DevTools remote attachment. |
disableContextMenu |
false |
Android/iOS | Disables long-press menus and touch selection interactions completely. |
disableLongPressContextMenuOnLinks |
false |
Android/iOS | Prevents special links preview/copy contextual windows specifically. |
selectionHandleColor |
null |
Android | Best effort: Stylizes text highlight color boundaries via runtime CSS injection. |
useHybridComposition |
true |
Android | Forces heavy rendering through native surface. Fixes scrolling and layout overlapping bugs. |
allowsBackForwardNavigationGestures |
false |
iOS | Enables edge swipe gesture history forward/backward navigations. |
allowsLinkPreview |
false |
iOS | Enables 3D Touch/Long Press link "Peek and Pop" preview panels. |
disableLinkHoverPreview |
true |
Desktop | Hides status bar hover URL strings appearing at the bottom of the pane (Windows). |
disablePrinting |
false |
Windows | Blocks implicit printing calls via keyboard hotkeys (Ctrl+P) or window.print(). |
Setup in MacOS #
Add this code in DebugProfile.entitlements and Release.entitlements to have acces in Internet in WebView and acces to all files in the computer.
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
⚠️ Known Limitations & Architecture Caveats #
- Windows & Linux (Advanced Composition): Both Windows (
Webview2) and Linux (WebKitWebview) use simplified window rendering strategies. True seamless stacking layouts (advanced transparency masks, multi-layered Flutter widgets directly over or under the web layer) may require unique configurations within the specific target OS shell runner. - Linux Overlay Architecture: Since Linux lacks generic
PlatformViewcomposition hooks inside Flutter's engine core, this plugin binds a direct nativeGtkWidgeton top of the Flutter window frame coordinates dynamically. Size, placement, and lifecycle updates are synchronised directly over global method channels. - Web Iframes Constraints:
onNavigationRequestis fully dependable only when loading content with matching origins (such as local bundled assets). Standard web browser security frames block cross-origin navigation interceptions on independent<iframe>nodes.
📝 Example #
For a complete working deployment showcase showcasing full bidirectional communication pipelines, layout changes, and asset mounting routines, review the detailed example/lib/main.dart source file.
📄 License #
Developed by Noam. Licensed under standard project conditions.