From f569e369f433d218dac78f43462c83be1c5c4b1d Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Thu, 21 May 2020 23:02:08 +0200 Subject: [PATCH] Updated Android context menu workaround, updated iOS onCreateContextMenu event, Added Android keyboard workaround to hide the keyboard when clicking other HTML elements --- CHANGELOG.md | 6 + .../InAppWebView/FlutterWebView.java | 6 - .../InAppWebView/InAppWebView.java | 103 ++++++++++++++---- .../InAppWebView/InAppWebViewClient.java | 4 + .../JavaScriptBridgeInterface.java | 15 +++ example/.flutter-plugins-dependencies | 2 +- .../ios/Flutter/flutter_export_environment.sh | 2 +- example/lib/in_app_webiew_example.screen.dart | 6 +- example/pubspec.yaml | 4 +- ios/Classes/InAppWebView.swift | 14 ++- lib/src/in_app_webview.dart | 3 +- lib/src/in_app_webview_controller.dart | 5 + pubspec.yaml | 2 +- 13 files changed, 134 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba6cfcdc..059338ff 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 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 - Added `ContextMenu` and `ContextMenuItem` classes [#235](https://github.com/pichillilorenzo/flutter_inappwebview/issues/235) diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java index 42770048..6cb537c3 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java @@ -1,22 +1,17 @@ package com.pichillilorenzo.flutter_inappwebview.InAppWebView; -import android.app.Activity; import android.content.Context; import android.hardware.display.DisplayManager; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.util.Log; -import android.view.ContextThemeWrapper; import android.view.View; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; 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.Util; @@ -29,7 +24,6 @@ import java.util.Map; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.PluginRegistry.Registrar; import io.flutter.plugin.platform.PlatformView; import static io.flutter.plugin.common.MethodChannel.MethodCallHandler; diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java index 4b54aee6..9f57e891 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java @@ -76,18 +76,17 @@ final public class InAppWebView extends InputAwareWebView { int okHttpClientCacheSize = 10 * 1024 * 1024; // 10MB public ContentBlockerHandler contentBlockerHandler = new ContentBlockerHandler(); public Pattern regexToCancelSubFramesLoadingCompiled; - private GestureDetector gestureDetector = null; - private MotionEvent motionEvent = null; - private LinearLayout floatingContextMenu = null; + public GestureDetector gestureDetector = null; + public LinearLayout floatingContextMenu = null; public HashMap contextMenu = null; public Handler headlessHandler = new Handler(Looper.getMainLooper()); - private Runnable checkScrollStoppedTask; - private int initialPositionScrollStoppedTask; - private int newCheckScrollStoppedTask = 100; + public Runnable checkScrollStoppedTask; + public int initialPositionScrollStoppedTask; + public int newCheckScrollStoppedTask = 100; // ms - private Runnable selectedTextTask; - private int newCheckSelectedTextTask = 100; + public Runnable checkContextMenuShouldBeClosedTask; + public int newCheckContextMenuShouldBeClosedTaskTask = 100; // ms static final String consoleLogJS = "(function(console) {" + " var oldLogs = {" + @@ -117,7 +116,7 @@ final public class InAppWebView extends InputAwareWebView { static final String printJS = "window.print = function() {" + " window." + JavaScriptBridgeInterface.name + ".callHandler('onPrint', window.location.href);" + - "}"; + "};"; static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));"; @@ -531,6 +530,14 @@ final public class InAppWebView extends InputAwareWebView { " };" + "})(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(){" + " var txt;" + " if (window.getSelection) {" + @@ -543,6 +550,48 @@ final public class InAppWebView extends InputAwareWebView { " 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) { super(context); } @@ -746,19 +795,19 @@ final public class InAppWebView extends InputAwareWebView { }; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - selectedTextTask = new Runnable() { + checkContextMenuShouldBeClosedTask = new Runnable() { @Override public void run() { if (floatingContextMenu != null) { - getSelectedText(new ValueCallback() { + evaluateJavascript(checkContextMenuShouldBeHiddenJS, new ValueCallback() { @Override public void onReceiveValue(String value) { - if (value == null || value.length() == 0) { + if (value == null || value.equals("true")) { if (floatingContextMenu != null) { hideContextMenu(); } } else { - headlessHandler.postDelayed(selectedTextTask, newCheckSelectedTextTask); + headlessHandler.postDelayed(checkContextMenuShouldBeClosedTask, newCheckContextMenuShouldBeClosedTaskTask); } } }); @@ -1424,14 +1473,18 @@ final public class InAppWebView extends InputAwareWebView { PrintManager printManager = (PrintManager) Shared.activity.getApplicationContext() .getSystemService(Context.PRINT_SERVICE); - String jobName = getTitle() + " Document"; + if (printManager != null) { + String jobName = getTitle() + " Document"; - // Get a printCurrentPage adapter instance - PrintDocumentAdapter printAdapter = createPrintDocumentAdapter(jobName); + // Get a printCurrentPage adapter instance + PrintDocumentAdapter printAdapter = createPrintDocumentAdapter(jobName); - // Create a printCurrentPage job with name and adapter instance - printManager.print(jobName, printAdapter, - new PrintAttributes.Builder().build()); + // Create a printCurrentPage job with name and adapter instance + printManager.print(jobName, printAdapter, + new PrintAttributes.Builder().build()); + } else { + Log.e(LOG_TAG, "No PrintManager available"); + } } public Float getUpdatedScale() { @@ -1444,6 +1497,12 @@ final public class InAppWebView extends InputAwareWebView { sendOnCreateContextMenuEvent(); } + @Override + public boolean onCheckIsTextEditor() { + Log.d(LOG_TAG, "onCheckIsTextEditor"); + return super.onCheckIsTextEditor(); + } + private void sendOnCreateContextMenuEvent() { HitTestResult hitTestResult = getHitTestResult(); Map hitTestResultMap = new HashMap<>(); @@ -1545,7 +1604,7 @@ final public class InAppWebView extends InputAwareWebView { text.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - clearFocus(); + // clearFocus(); hideContextMenu(); Map obj = new HashMap<>(); @@ -1588,8 +1647,8 @@ final public class InAppWebView extends InputAwareWebView { if (hasBeenRemovedAndRebuilt) { sendOnCreateContextMenuEvent(); } - if (selectedTextTask != null) { - selectedTextTask.run(); + if (checkContextMenuShouldBeClosedTask != null) { + checkContextMenuShouldBeClosedTask.run(); } } actionMenu.clear(); diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java index 02d15956..e0487490 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java @@ -179,6 +179,10 @@ public class InAppWebViewClient extends WebViewClient { if (webView.options.useOnLoadResource) { 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]+", ""); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java index 4a7b3003..b1095706 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java @@ -44,6 +44,21 @@ public class JavaScriptBridgeInterface { 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 public void _callHandler(final String handlerName, final String _callHandlerID, final String args) { final InAppWebView webView = (inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView; diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies index d20e9c1b..489fe968 100755 --- a/example/.flutter-plugins-dependencies +++ b/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"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"} \ No newline at end of file +{"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 diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index 2dce6e0f..fb55de39 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -2,7 +2,7 @@ # This is a generated file; do not edit or check into version control. export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter" 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 "SYMROOT=${SOURCE_ROOT}/../build/ios" export "OTHER_LDFLAGS=$(inherited) -framework Flutter" diff --git a/example/lib/in_app_webiew_example.screen.dart b/example/lib/in_app_webiew_example.screen.dart index 46bf16f5..88c90292 100755 --- a/example/lib/in_app_webiew_example.screen.dart +++ b/example/lib/in_app_webiew_example.screen.dart @@ -1,6 +1,9 @@ import 'dart:io'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'main.dart'; @@ -78,7 +81,8 @@ class _InAppWebViewExampleScreenState extends State { initialHeaders: {}, initialOptions: InAppWebViewGroupOptions( crossPlatform: InAppWebViewOptions( - debuggingEnabled: true + debuggingEnabled: true, + disableContextMenu: true, ), ), onWebViewCreated: (InAppWebViewController controller) { diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 9d78e869..03b96b04 100755 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -24,8 +24,8 @@ dependencies: path_provider: ^1.4.0 permission_handler: ^3.3.0 connectivity: ^0.4.5+6 - flutter_inappwebview: - path: ../ + flutter_inappwebview: ^3.2.0 + #path: ../ dev_dependencies: flutter_driver: diff --git a/ios/Classes/InAppWebView.swift b/ios/Classes/InAppWebView.swift index 6d3a0319..54f8933d 100755 --- a/ios/Classes/InAppWebView.swift +++ b/ios/Classes/InAppWebView.swift @@ -763,6 +763,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi var lastTouchPointTimestamp = Int64(Date().timeIntervalSince1970 * 1000) var contextMenuIsShowing = false + // flag used for the workaround to trigger onCreateContextMenu event as the same on Android + var onCreateContextMenuEventTriggeredWhenMenuDisabled = false var customIMPs: [IMP] = [] @@ -887,10 +889,18 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi return super.hitTest(point, with: event) } - + public override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { if let _ = sender as? UIMenuController { 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 } if contextMenuIsShowing, !action.description.starts(with: "onContextMenuActionItemClicked-") { @@ -1083,8 +1093,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi if (options?.clearCache)! { clearCache() } - - } @available(iOS 10.0, *) diff --git a/lib/src/in_app_webview.dart b/lib/src/in_app_webview.dart index a7264d78..9b930a49 100755 --- a/lib/src/in_app_webview.dart +++ b/lib/src/in_app_webview.dart @@ -18,7 +18,8 @@ const javaScriptHandlerForbiddenNames = [ "onAjaxReadyStateChange", "onAjaxProgress", "shouldInterceptFetchRequest", - "onPrint" + "onPrint", + "androidKeyboardWorkaroundFocusoutEvent" ]; ///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree. diff --git a/lib/src/in_app_webview_controller.dart b/lib/src/in_app_webview_controller.dart index 1f5c7051..958da8d4 100644 --- a/lib/src/in_app_webview_controller.dart +++ b/lib/src/in_app_webview_controller.dart @@ -439,6 +439,11 @@ class InAppWebViewController { List args = jsonDecode(call.arguments["args"]); 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": Map argMap = args[0]; String initiatorType = argMap["initiatorType"]; diff --git a/pubspec.yaml b/pubspec.yaml index 5797ab05..07e2c70d 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_inappwebview 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 environment: