diff --git a/ios/Classes/FlutterWebviewPlugin.m b/ios/Classes/FlutterWebviewPlugin.m index fc266094..dd7a3d1b 100644 --- a/ios/Classes/FlutterWebviewPlugin.m +++ b/ios/Classes/FlutterWebviewPlugin.m @@ -196,16 +196,10 @@ - (void)navigate:(FlutterMethodCall*)call { NSString *url = call.arguments[@"url"]; NSNumber *withLocalUrl = call.arguments[@"withLocalUrl"]; if ( [withLocalUrl boolValue]) { - NSURL *htmlUrl = [NSURL fileURLWithPath:url isDirectory:false]; - NSString *localUrlScope = call.arguments[@"localUrlScope"]; if (@available(iOS 9.0, *)) { - if(localUrlScope == nil) { - [self.webview loadFileURL:htmlUrl allowingReadAccessToURL:htmlUrl]; - } - else { - NSURL *scopeUrl = [NSURL fileURLWithPath:localUrlScope]; - [self.webview loadFileURL:htmlUrl allowingReadAccessToURL:scopeUrl]; - } + NSURL *scopeUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; + NSURL *fileUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:url ofType:nil]]; + [self.webview loadFileURL:fileUrl allowingReadAccessToURL:scopeUrl]; } else { @throw @"not available on version earlier than ios 9.0"; } diff --git a/lib/src/base.dart b/lib/src/base.dart index 2fdc0384..2814d811 100644 --- a/lib/src/base.dart +++ b/lib/src/base.dart @@ -12,6 +12,13 @@ const _kChannel = 'flutter_webview_plugin'; // TODO: more general state for iOS/android enum WebViewState { shouldStart, startLoad, finishLoad, abortLoad } +/// the transition animation type of page on/off screen +enum TransitionType { + Non, + Slide +} + + // TODO: use an id by webview to be able to manage multiple webview /// Singleton class that communicate with a Webview Instance @@ -44,7 +51,7 @@ class FlutterWebviewPlugin { final _onPostMessage = StreamController.broadcast(); final Map _javascriptChannels = - {}; + {}; Future _handleMessages(MethodCall call) async { switch (call.method) { @@ -139,8 +146,7 @@ class FlutterWebviewPlugin { /// - [withOverviewMode]: enable overview mode for Android webview ( setLoadWithOverviewMode ) /// - [useWideViewPort]: use wide viewport for Android webview ( setUseWideViewPort ) /// - [ignoreSSLErrors]: use to bypass Android/iOS SSL checks e.g. for self-signed certificates - Future launch( - String url, { + Future launch(String url, { Map? headers, Set javascriptChannels = const {}, bool withJavascript = true, @@ -317,12 +323,11 @@ class FlutterWebviewPlugin { Set _extractJavascriptChannelNames(Set channels) { final Set channelNames = - channels.map((JavascriptChannel channel) => channel.name).toSet(); + channels.map((JavascriptChannel channel) => channel.name).toSet(); return channelNames; } - void _handleJavascriptChannelMessage( - final String channelName, final String message) { + void _handleJavascriptChannelMessage(final String channelName, final String message) { if (_javascriptChannels.containsKey(channelName)) _javascriptChannels[channelName]! .onMessageReceived(JavascriptMessage(message)); @@ -330,8 +335,7 @@ class FlutterWebviewPlugin { print('Channel "$channelName" is not exstis'); } - void _assertJavascriptChannelNamesAreUnique( - final Set? channels) { + void _assertJavascriptChannelNamesAreUnique(final Set? channels) { if (channels == null || channels.isEmpty) { return; } diff --git a/lib/src/webview_scaffold.dart b/lib/src/webview_scaffold.dart index 389add90..71e8b214 100644 --- a/lib/src/webview_scaffold.dart +++ b/lib/src/webview_scaffold.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -10,6 +11,8 @@ import 'base.dart'; class WebviewScaffold extends StatefulWidget { const WebviewScaffold({ Key? key, + required this.rrok, + required this.margin, this.appBar, required this.url, this.headers, @@ -41,7 +44,22 @@ class WebviewScaffold extends StatefulWidget { this.geolocationEnabled = false, this.debuggingEnabled = false, this.ignoreSSLErrors = false, - }) : super(key: key); + this.transitionType = TransitionType.Non + }) + : + assert(transitionType != null, 'TransitionType must not null !'), + super(key: key); + + // The global key of the referenced render object + final GlobalKey rrok; + + final EdgeInsets margin; + + /// in Debug mode,the first init webview page at slide/scale transition,will display misalignment + /// after that will be display properly. + /// + /// in Profile/Release mode, will always display properly. + final TransitionType transitionType; final PreferredSizeWidget? appBar; final String url; @@ -92,6 +110,8 @@ class _WebviewScaffoldState extends State { super.initState(); webviewReference.close(); + perceptionPageTransition(); + _onBack = webviewReference.onBack.listen((_) async { if (!mounted) { return; @@ -113,13 +133,40 @@ class _WebviewScaffoldState extends State { if (widget.hidden) { _onStateChanged = webviewReference.onStateChanged.listen((WebViewStateChanged state) { - if (state.type == WebViewState.finishLoad) { - webviewReference.show(); - } + if (state.type == WebViewState.finishLoad) { + webviewReference.show(); + } + }); + } + } + + /// coordinate the webview rect whit page's transition + void perceptionPageTransition() { + if (widget.transitionType != TransitionType.Non) { + WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { + //avoid to concurrent modification exception + WidgetsBinding.instance?.addPersistentFrameCallback((timeStamp) { + if (mounted) { + driveWebView(); + } + }); }); } } + void driveWebView() { + switch (widget.transitionType) { + case TransitionType.Slide: + final RenderBox box = widget.rrok.currentContext?.findRenderObject()! as RenderBox; + final Offset offset = box.localToGlobal(Offset.zero) + Offset(widget.margin.left != null ? widget.margin.left : 0.0, widget.margin.top != null ? widget.margin.top : 0.0); + webviewReference.resize(_rect!.shift(offset)); + break; + case TransitionType.Non: + // TODO: Handle this case. + break; + } + } + /// Equivalent to [Navigator.of(context)._history.last]. Route get _topMostRoute { Route? topMost; @@ -161,7 +208,7 @@ class _WebviewScaffoldState extends State { clearCache: widget.clearCache, clearCookies: widget.clearCookies, mediaPlaybackRequiresUserGesture: - widget.mediaPlaybackRequiresUserGesture, + widget.mediaPlaybackRequiresUserGesture, hidden: widget.hidden, enableAppScheme: widget.enableAppScheme, userAgent: widget.userAgent, @@ -217,8 +264,7 @@ class _WebviewPlaceholder extends SingleChildRenderObjectWidget { } @override - void updateRenderObject( - BuildContext context, _WebviewPlaceholderRender renderObject) { + void updateRenderObject(BuildContext context, _WebviewPlaceholderRender renderObject) { renderObject..onRectChanged = onRectChanged; } } @@ -227,7 +273,8 @@ class _WebviewPlaceholderRender extends RenderProxyBox { _WebviewPlaceholderRender({ RenderBox? child, ValueChanged? onRectChanged, - }) : _callback = onRectChanged, + }) + : _callback = onRectChanged, super(child); ValueChanged? _callback;