Updated Android context menu workaround, updated iOS onCreateContextMenu event, Added Android keyboard workaround to hide the keyboard when clicking other HTML elements

This commit is contained in:
Lorenzo Pichilli 2020-05-21 23:02:08 +02:00
parent 5943059b1d
commit f569e369f4
13 changed files with 134 additions and 38 deletions

View File

@ -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 ## 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)

View File

@ -1,22 +1,17 @@
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;
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;

View File

@ -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 {
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 {
" };" + " };" +
"})(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 {
" 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 {
}; };
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,14 +1473,18 @@ 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);
String jobName = getTitle() + " Document"; if (printManager != null) {
String jobName = getTitle() + " Document";
// Get a printCurrentPage adapter instance // Get a printCurrentPage adapter instance
PrintDocumentAdapter printAdapter = createPrintDocumentAdapter(jobName); PrintDocumentAdapter printAdapter = createPrintDocumentAdapter(jobName);
// 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 {
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 {
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 {
if (hasBeenRemovedAndRebuilt) { if (hasBeenRemovedAndRebuilt) {
sendOnCreateContextMenuEvent(); sendOnCreateContextMenuEvent();
} }
if (selectedTextTask != null) { if (checkContextMenuShouldBeClosedTask != null) {
selectedTextTask.run(); checkContextMenuShouldBeClosedTask.run();
} }
} }
actionMenu.clear(); actionMenu.clear();

View File

@ -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) {

View File

@ -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;

View File

@ -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"} {"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"}

View File

@ -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"

View File

@ -1,6 +1,9 @@
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> {
initialHeaders: {}, initialHeaders: {},
initialOptions: InAppWebViewGroupOptions( initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions( crossPlatform: InAppWebViewOptions(
debuggingEnabled: true debuggingEnabled: true,
disableContextMenu: true,
), ),
), ),
onWebViewCreated: (InAppWebViewController controller) { onWebViewCreated: (InAppWebViewController controller) {

View File

@ -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:

View File

@ -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] = []
@ -887,10 +889,18 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
return super.hitTest(point, with: event) return super.hitTest(point, with: event)
} }
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
if (options?.clearCache)! { if (options?.clearCache)! {
clearCache() clearCache()
} }
} }
@available(iOS 10.0, *) @available(iOS 10.0, *)

View File

@ -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.

View File

@ -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"];

View File

@ -1,6 +1,6 @@
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: