Commit f569e369 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

Updated Android context menu workaround, updated iOS onCreateContextMenu...

Updated Android context menu workaround, updated iOS onCreateContextMenu event, Added Android keyboard workaround to hide the keyboard when clicking other HTML elements
parent 5943059b
## 3.3.0
- Updated Android context menu workaround
- Calling `onCreateContextMenu` event on iOS also when the context menu is disabled in order to have the same effect as Android
- Added Android keyboard workaround to hide the keyboard when clicking other HTML elements, losing the focus on the previous input
## 3.2.0 ## 3.2.0
- Added `ContextMenu` and `ContextMenuItem` classes [#235](https://github.com/pichillilorenzo/flutter_inappwebview/issues/235) - Added `ContextMenu` and `ContextMenuItem` classes [#235](https://github.com/pichillilorenzo/flutter_inappwebview/issues/235)
......
package com.pichillilorenzo.flutter_inappwebview.InAppWebView; package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.View; import android.view.View;
import android.webkit.WebChromeClient; import android.webkit.WebChromeClient;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.DisplayListenerProxy;
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebView;
import com.pichillilorenzo.flutter_inappwebview.InAppWebView.InAppWebViewOptions;
import com.pichillilorenzo.flutter_inappwebview.Shared; import com.pichillilorenzo.flutter_inappwebview.Shared;
import com.pichillilorenzo.flutter_inappwebview.Util; import com.pichillilorenzo.flutter_inappwebview.Util;
...@@ -29,7 +24,6 @@ import java.util.Map; ...@@ -29,7 +24,6 @@ import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.platform.PlatformView; import io.flutter.plugin.platform.PlatformView;
import static io.flutter.plugin.common.MethodChannel.MethodCallHandler; import static io.flutter.plugin.common.MethodChannel.MethodCallHandler;
......
...@@ -76,18 +76,17 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -76,18 +76,17 @@ final public class InAppWebView extends InputAwareWebView {
int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB
public ContentBlockerHandler contentBlockerHandler = new ContentBlockerHandler(); public ContentBlockerHandler contentBlockerHandler = new ContentBlockerHandler();
public Pattern regexToCancelSubFramesLoadingCompiled; public Pattern regexToCancelSubFramesLoadingCompiled;
private GestureDetector gestureDetector = null; public GestureDetector gestureDetector = null;
private MotionEvent motionEvent = null; public LinearLayout floatingContextMenu = null;
private LinearLayout floatingContextMenu = null;
public HashMap<String, Object> contextMenu = null; public HashMap<String, Object> contextMenu = null;
public Handler headlessHandler = new Handler(Looper.getMainLooper()); public Handler headlessHandler = new Handler(Looper.getMainLooper());
private Runnable checkScrollStoppedTask; public Runnable checkScrollStoppedTask;
private int initialPositionScrollStoppedTask; public int initialPositionScrollStoppedTask;
private int newCheckScrollStoppedTask = 100; public int newCheckScrollStoppedTask = 100; // ms
private Runnable selectedTextTask; public Runnable checkContextMenuShouldBeClosedTask;
private int newCheckSelectedTextTask = 100; public int newCheckContextMenuShouldBeClosedTaskTask = 100; // ms
static final String consoleLogJS = "(function(console) {" + static final String consoleLogJS = "(function(console) {" +
" var oldLogs = {" + " var oldLogs = {" +
...@@ -117,7 +116,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -117,7 +116,7 @@ final public class InAppWebView extends InputAwareWebView {
static final String printJS = "window.print = function() {" + static final String printJS = "window.print = function() {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('onPrint', window.location.href);" + " window." + JavaScriptBridgeInterface.name + ".callHandler('onPrint', window.location.href);" +
"}"; "};";
static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));"; static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));";
...@@ -531,6 +530,14 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -531,6 +530,14 @@ final public class InAppWebView extends InputAwareWebView {
" };" + " };" +
"})(window.fetch);"; "})(window.fetch);";
static final String isActiveElementInputEditableJS =
"var activeEl = document.activeElement;" +
"var nodeName = (activeEl != null) ? activeEl.nodeName.toLowerCase() : '';" +
"var isActiveElementInputEditable = activeEl != null && " +
"(activeEl.nodeType == 1 && (nodeName == 'textarea' || (nodeName == 'input' && /^(?:text|email|number|search|tel|url|password)$/i.test(activeEl.type != null ? activeEl.type : 'text')))) && " +
"!activeEl.disabled && !activeEl.readOnly;" +
"var isActiveElementEditable = isActiveElementInputEditable || (activeEl != null && activeEl.isContentEditable) || document.designMode === 'on';";
static final String getSelectedTextJS = "(function(){" + static final String getSelectedTextJS = "(function(){" +
" var txt;" + " var txt;" +
" if (window.getSelection) {" + " if (window.getSelection) {" +
...@@ -543,6 +550,48 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -543,6 +550,48 @@ final public class InAppWebView extends InputAwareWebView {
" return txt;" + " return txt;" +
"})();"; "})();";
// android Workaround to hide context menu when selected text is empty
// and the document active element is not an input element.
static final String checkContextMenuShouldBeHiddenJS = "(function(){" +
" var txt;" +
" if (window.getSelection) {" +
" txt = window.getSelection().toString();" +
" } else if (window.document.getSelection) {" +
" txt = window.document.getSelection().toString();" +
" } else if (window.document.selection) {" +
" txt = window.document.selection.createRange().text;" +
" }" +
isActiveElementInputEditableJS +
" return txt === '' && !isActiveElementEditable;" +
"})();";
// android Workaround to hide context menu when user emit a keydown event
static final String checkGlobalKeyDownEventToHideContextMenuJS = "(function(){" +
" document.addEventListener('keydown', function(e) {" +
" window." + JavaScriptBridgeInterface.name + "._hideContextMenu();" +
" });" +
"})();";
// android Workaround to hide the Keyboard when the user click outside
// on something not focusable such as input or a textarea.
static final String androidKeyboardWorkaroundFocusoutEventJS = "(function(){" +
" var isFocusin = false;" +
" document.addEventListener('focusin', function(e) {" +
" var nodeName = e.target.nodeName.toLowerCase();" +
" var isInputButton = nodeName === 'input' && e.target.type != null && e.target.type === 'button';" +
" isFocusin = (['a', 'area', 'button', 'details', 'iframe', 'select', 'summary'].indexOf(nodeName) >= 0 || isInputButton) ? false : true;" +
" });" +
" document.addEventListener('focusout', function(e) {" +
" isFocusin = false;" +
" setTimeout(function() {" +
isActiveElementInputEditableJS +
" if (!isFocusin && !isActiveElementEditable) {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('androidKeyboardWorkaroundFocusoutEvent');" +
" }" +
" }, 300);" +
" });" +
"})();";
public InAppWebView(Context context) { public InAppWebView(Context context) {
super(context); super(context);
} }
...@@ -746,19 +795,19 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -746,19 +795,19 @@ final public class InAppWebView extends InputAwareWebView {
}; };
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
selectedTextTask = new Runnable() { checkContextMenuShouldBeClosedTask = new Runnable() {
@Override @Override
public void run() { public void run() {
if (floatingContextMenu != null) { if (floatingContextMenu != null) {
getSelectedText(new ValueCallback<String>() { evaluateJavascript(checkContextMenuShouldBeHiddenJS, new ValueCallback<String>() {
@Override @Override
public void onReceiveValue(String value) { public void onReceiveValue(String value) {
if (value == null || value.length() == 0) { if (value == null || value.equals("true")) {
if (floatingContextMenu != null) { if (floatingContextMenu != null) {
hideContextMenu(); hideContextMenu();
} }
} else { } else {
headlessHandler.postDelayed(selectedTextTask, newCheckSelectedTextTask); headlessHandler.postDelayed(checkContextMenuShouldBeClosedTask, newCheckContextMenuShouldBeClosedTaskTask);
} }
} }
}); });
...@@ -1424,6 +1473,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1424,6 +1473,7 @@ final public class InAppWebView extends InputAwareWebView {
PrintManager printManager = (PrintManager) Shared.activity.getApplicationContext() PrintManager printManager = (PrintManager) Shared.activity.getApplicationContext()
.getSystemService(Context.PRINT_SERVICE); .getSystemService(Context.PRINT_SERVICE);
if (printManager != null) {
String jobName = getTitle() + " Document"; String jobName = getTitle() + " Document";
// Get a printCurrentPage adapter instance // Get a printCurrentPage adapter instance
...@@ -1432,6 +1482,9 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1432,6 +1482,9 @@ final public class InAppWebView extends InputAwareWebView {
// Create a printCurrentPage job with name and adapter instance // Create a printCurrentPage job with name and adapter instance
printManager.print(jobName, printAdapter, printManager.print(jobName, printAdapter,
new PrintAttributes.Builder().build()); new PrintAttributes.Builder().build());
} else {
Log.e(LOG_TAG, "No PrintManager available");
}
} }
public Float getUpdatedScale() { public Float getUpdatedScale() {
...@@ -1444,6 +1497,12 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1444,6 +1497,12 @@ final public class InAppWebView extends InputAwareWebView {
sendOnCreateContextMenuEvent(); sendOnCreateContextMenuEvent();
} }
@Override
public boolean onCheckIsTextEditor() {
Log.d(LOG_TAG, "onCheckIsTextEditor");
return super.onCheckIsTextEditor();
}
private void sendOnCreateContextMenuEvent() { private void sendOnCreateContextMenuEvent() {
HitTestResult hitTestResult = getHitTestResult(); HitTestResult hitTestResult = getHitTestResult();
Map<String, Object> hitTestResultMap = new HashMap<>(); Map<String, Object> hitTestResultMap = new HashMap<>();
...@@ -1545,7 +1604,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1545,7 +1604,7 @@ final public class InAppWebView extends InputAwareWebView {
text.setOnClickListener(new OnClickListener() { text.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
clearFocus(); // clearFocus();
hideContextMenu(); hideContextMenu();
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
...@@ -1588,8 +1647,8 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1588,8 +1647,8 @@ final public class InAppWebView extends InputAwareWebView {
if (hasBeenRemovedAndRebuilt) { if (hasBeenRemovedAndRebuilt) {
sendOnCreateContextMenuEvent(); sendOnCreateContextMenuEvent();
} }
if (selectedTextTask != null) { if (checkContextMenuShouldBeClosedTask != null) {
selectedTextTask.run(); checkContextMenuShouldBeClosedTask.run();
} }
} }
actionMenu.clear(); actionMenu.clear();
......
...@@ -179,6 +179,10 @@ public class InAppWebViewClient extends WebViewClient { ...@@ -179,6 +179,10 @@ public class InAppWebViewClient extends WebViewClient {
if (webView.options.useOnLoadResource) { if (webView.options.useOnLoadResource) {
js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", ""); js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", "");
} }
js += InAppWebView.checkGlobalKeyDownEventToHideContextMenuJS.replaceAll("[\r\n]+", "");
if (flutterWebView != null) {
js += InAppWebView.androidKeyboardWorkaroundFocusoutEventJS.replaceAll("[\r\n]+", "");
}
js += InAppWebView.printJS.replaceAll("[\r\n]+", ""); js += InAppWebView.printJS.replaceAll("[\r\n]+", "");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
......
...@@ -44,6 +44,21 @@ public class JavaScriptBridgeInterface { ...@@ -44,6 +44,21 @@ public class JavaScriptBridgeInterface {
this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel; this.channel = (this.inAppBrowserActivity != null) ? this.inAppBrowserActivity.channel : this.flutterWebView.channel;
} }
@JavascriptInterface
public void _hideContextMenu() {
final InAppWebView webView = (inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView;
final Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
if (webView != null && webView.floatingContextMenu != null) {
webView.hideContextMenu();
}
}
});
}
@JavascriptInterface @JavascriptInterface
public void _callHandler(final String handlerName, final String _callHandlerID, final String args) { public void _callHandler(final String handlerName, final String _callHandlerID, final String args) {
final InAppWebView webView = (inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView; final InAppWebView webView = (inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView;
......
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"android":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"macos":[{"name":"connectivity_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_macos-0.1.0+3/","dependencies":[]},{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"connectivity","dependencies":["connectivity_macos"]},{"name":"connectivity_macos","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-21 03:31:36.578209","version":"1.17.0"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_inappwebview-3.2.0/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"android":[{"name":"connectivity","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.8+5/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_inappwebview-3.2.0/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.7/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-3.3.0/","dependencies":[]}],"macos":[{"name":"connectivity_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_macos-0.1.0+3/","dependencies":[]},{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"connectivity","dependencies":["connectivity_macos"]},{"name":"connectivity_macos","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-21 22:50:56.107907","version":"1.17.0"}
\ No newline at end of file \ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# This is a generated file; do not edit or check into version control. # This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter" export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/test_driver/app.dart" export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart"
export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios" export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "OTHER_LDFLAGS=$(inherited) -framework Flutter" export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
......
import 'dart:io'; import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'main.dart'; import 'main.dart';
...@@ -78,7 +81,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -78,7 +81,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
initialHeaders: {}, initialHeaders: {},
initialOptions: InAppWebViewGroupOptions( initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions( crossPlatform: InAppWebViewOptions(
debuggingEnabled: true debuggingEnabled: true,
disableContextMenu: true,
), ),
), ),
onWebViewCreated: (InAppWebViewController controller) { onWebViewCreated: (InAppWebViewController controller) {
......
...@@ -24,8 +24,8 @@ dependencies: ...@@ -24,8 +24,8 @@ dependencies:
path_provider: ^1.4.0 path_provider: ^1.4.0
permission_handler: ^3.3.0 permission_handler: ^3.3.0
connectivity: ^0.4.5+6 connectivity: ^0.4.5+6
flutter_inappwebview: flutter_inappwebview: ^3.2.0
path: ../ #path: ../
dev_dependencies: dev_dependencies:
flutter_driver: flutter_driver:
......
...@@ -763,6 +763,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi ...@@ -763,6 +763,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
var lastTouchPointTimestamp = Int64(Date().timeIntervalSince1970 * 1000) var lastTouchPointTimestamp = Int64(Date().timeIntervalSince1970 * 1000)
var contextMenuIsShowing = false var contextMenuIsShowing = false
// flag used for the workaround to trigger onCreateContextMenu event as the same on Android
var onCreateContextMenuEventTriggeredWhenMenuDisabled = false
var customIMPs: [IMP] = [] var customIMPs: [IMP] = []
...@@ -891,6 +893,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi ...@@ -891,6 +893,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
public override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { public override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if let _ = sender as? UIMenuController { if let _ = sender as? UIMenuController {
if self.options?.disableContextMenu == true { if self.options?.disableContextMenu == true {
if !onCreateContextMenuEventTriggeredWhenMenuDisabled {
// workaround to trigger onCreateContextMenu event as the same on Android
self.onCreateContextMenu()
onCreateContextMenuEventTriggeredWhenMenuDisabled = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.onCreateContextMenuEventTriggeredWhenMenuDisabled = false
}
}
return false return false
} }
if contextMenuIsShowing, !action.description.starts(with: "onContextMenuActionItemClicked-") { if contextMenuIsShowing, !action.description.starts(with: "onContextMenuActionItemClicked-") {
...@@ -1083,8 +1093,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi ...@@ -1083,8 +1093,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
if (options?.clearCache)! { if (options?.clearCache)! {
clearCache() clearCache()
} }
} }
@available(iOS 10.0, *) @available(iOS 10.0, *)
......
...@@ -18,7 +18,8 @@ const javaScriptHandlerForbiddenNames = [ ...@@ -18,7 +18,8 @@ const javaScriptHandlerForbiddenNames = [
"onAjaxReadyStateChange", "onAjaxReadyStateChange",
"onAjaxProgress", "onAjaxProgress",
"shouldInterceptFetchRequest", "shouldInterceptFetchRequest",
"onPrint" "onPrint",
"androidKeyboardWorkaroundFocusoutEvent"
]; ];
///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree. ///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree.
......
...@@ -439,6 +439,11 @@ class InAppWebViewController { ...@@ -439,6 +439,11 @@ class InAppWebViewController {
List<dynamic> args = jsonDecode(call.arguments["args"]); List<dynamic> args = jsonDecode(call.arguments["args"]);
switch (handlerName) { switch (handlerName) {
case "androidKeyboardWorkaroundFocusoutEvent":
// android Workaround to hide the Keyboard when the user click outside
// on something not focusable such as input or a textarea.
SystemChannels.textInput.invokeMethod("TextInput.hide");
break;
case "onLoadResource": case "onLoadResource":
Map<dynamic, dynamic> argMap = args[0]; Map<dynamic, dynamic> argMap = args[0];
String initiatorType = argMap["initiatorType"]; String initiatorType = argMap["initiatorType"];
......
name: flutter_inappwebview name: flutter_inappwebview
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window. description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window.
version: 3.2.0 version: 3.3.0
homepage: https://github.com/pichillilorenzo/flutter_inappwebview homepage: https://github.com/pichillilorenzo/flutter_inappwebview
environment: environment:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment