Commit 9f9232e1 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

added clearHistory webview methods on Android, setContextMenu and clearFocus...

added clearHistory webview methods on Android, setContextMenu and clearFocus webview methods, added ContextMenuOptions class
parent ad56ca66
...@@ -3,12 +3,14 @@ ...@@ -3,12 +3,14 @@
- Updated API docs - Updated API docs
- Updated Android context menu workaround - 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 - Calling `onCreateContextMenu` event on iOS also when the context menu is disabled in order to have the same effect as Android
- Added `options` attribute to `ContextMenu` class and created `ContextMenuOptions` class
- Added Android keyboard workaround to hide the keyboard when clicking other HTML elements, losing the focus on the previous input - Added Android keyboard workaround to hide the keyboard when clicking other HTML elements, losing the focus on the previous input
- Added `onEnterFullscreen`, `onExitFullscreen` webview events [#275](https://github.com/pichillilorenzo/flutter_inappwebview/issues/275) - Added `onEnterFullscreen`, `onExitFullscreen` webview events [#275](https://github.com/pichillilorenzo/flutter_inappwebview/issues/275)
- Added Android support to use camera on HTML inputs that requires it, such as `<input type="file" accept="image/*" capture>` [#353](https://github.com/pichillilorenzo/flutter_inappwebview/issues/353) - Added Android support to use camera on HTML inputs that requires it, such as `<input type="file" accept="image/*" capture>` [#353](https://github.com/pichillilorenzo/flutter_inappwebview/issues/353)
- Added `overScrollMode`, `networkAvailable`, `scrollBarStyle`, `verticalScrollbarPosition`, `scrollBarDefaultDelayBeforeFade`, `scrollbarFadingEnabled`, `scrollBarFadeDuration`, `rendererPriorityPolicy`, `useShouldInterceptRequest`, `useOnRenderProcessGone` webview options on Android - Added `overScrollMode`, `networkAvailable`, `scrollBarStyle`, `verticalScrollbarPosition`, `scrollBarDefaultDelayBeforeFade`, `scrollbarFadingEnabled`, `scrollBarFadeDuration`, `rendererPriorityPolicy`, `useShouldInterceptRequest`, `useOnRenderProcessGone` webview options on Android
- Added `pageDown`, `pageUp`, `saveWebArchive`, `zoomIn`, `zoomOut` webview methods on Android - Added `pageDown`, `pageUp`, `saveWebArchive`, `zoomIn`, `zoomOut`, `clearHistory` webview methods on Android
- Added `getCurrentWebViewPackage` static webview method on Android - Added `getCurrentWebViewPackage` static webview method on Android
- Added `setContextMenu`, `clearFocus` methods to webview controller
- Added `onPageCommitVisible` webview event - Added `onPageCommitVisible` webview event
- Added `androidShouldInterceptRequest`, `androidOnRenderProcessUnresponsive`, `androidOnRenderProcessResponsive`, `androidOnRenderProcessGone`, `androidOnFormResubmission`, `androidOnScaleChanged` Android events - Added `androidShouldInterceptRequest`, `androidOnRenderProcessUnresponsive`, `androidOnRenderProcessResponsive`, `androidOnRenderProcessGone`, `androidOnFormResubmission`, `androidOnScaleChanged` Android events
- Added `toString()` method to various classes in order to have a better output instead of simply `Instance of ...` - Added `toString()` method to various classes in order to have a better output instead of simply `Instance of ...`
...@@ -23,6 +25,7 @@ ...@@ -23,6 +25,7 @@
- Android `clearClientCertPreferences`, `getSafeBrowsingPrivacyPolicyUrl`, `setSafeBrowsingWhitelist` webview methods are static now - Android `clearClientCertPreferences`, `getSafeBrowsingPrivacyPolicyUrl`, `setSafeBrowsingWhitelist` webview methods are static now
- Removed iOS event `onDidCommit`; it has been renamed to `onPageCommitVisible` and made cross-platform - Removed iOS event `onDidCommit`; it has been renamed to `onPageCommitVisible` and made cross-platform
- `contextMenu` is `final` now
## 3.2.0 ## 3.2.0
......
...@@ -400,6 +400,8 @@ Screenshots: ...@@ -400,6 +400,8 @@ Screenshots:
* `getScale`: Gets the current scale of this WebView. * `getScale`: Gets the current scale of this WebView.
* `getSelectedText`: Gets the selected text. * `getSelectedText`: Gets the selected text.
* `getHitTestResult`: Gets the hit result for hitting an HTML elements. * `getHitTestResult`: Gets the hit result for hitting an HTML elements.
* `clearFocus`: Clears the current focus. It will clear also, for example, the current text selection.
* `setContextMenu(ContextMenu contextMenu)`: Sets or updates the WebView context menu to be used next time it will appear.
* `static getDefaultUserAgent`: Gets the default user agent. * `static getDefaultUserAgent`: Gets the default user agent.
##### `InAppWebViewController` Android-specific methods ##### `InAppWebViewController` Android-specific methods
...@@ -416,6 +418,7 @@ Android-specific methods can be called using the `InAppWebViewController.android ...@@ -416,6 +418,7 @@ Android-specific methods can be called using the `InAppWebViewController.android
* `saveWebArchive({@required String basename, @required bool autoname})`: Saves the current view as a web archive. * `saveWebArchive({@required String basename, @required bool autoname})`: Saves the current view as a web archive.
* `zoomIn`: Performs zoom in in this WebView. * `zoomIn`: Performs zoom in in this WebView.
* `zoomOut`: Performs zoom out in this WebView. * `zoomOut`: Performs zoom out in this WebView.
* `clearHistory`: Clears the internal back/forward list.
* `static clearClientCertPreferences`: Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests. * `static clearClientCertPreferences`: Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests.
* `static getSafeBrowsingPrivacyPolicyUrl`: Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`. * `static getSafeBrowsingPrivacyPolicyUrl`: Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`.
* `static setSafeBrowsingWhitelist({@required List<String> hosts})`: Sets the list of hosts (domain names/IP addresses) that are exempt from SafeBrowsing checks. The list is global for all the WebViews. * `static setSafeBrowsingWhitelist({@required List<String> hosts})`: Sets the list of hosts (domain names/IP addresses) that are exempt from SafeBrowsing checks. The list is global for all the WebViews.
...@@ -665,6 +668,11 @@ class _MyAppState extends State<MyApp> { ...@@ -665,6 +668,11 @@ class _MyAppState extends State<MyApp> {
super.initState(); super.initState();
contextMenu = ContextMenu( contextMenu = ContextMenu(
menuItems: [
ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async {
print("Menu item Special clicked!");
})
],
onCreateContextMenu: (hitTestResult) async { onCreateContextMenu: (hitTestResult) async {
print("onCreateContextMenu"); print("onCreateContextMenu");
print(hitTestResult.extra); print(hitTestResult.extra);
...@@ -679,12 +687,6 @@ class _MyAppState extends State<MyApp> { ...@@ -679,12 +687,6 @@ class _MyAppState extends State<MyApp> {
} }
); );
contextMenu.menuItems = [
ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async {
print("Menu item Special clicked!");
})
];
} }
@override @override
...@@ -782,6 +784,10 @@ class _MyAppState extends State<MyApp> { ...@@ -782,6 +784,10 @@ class _MyAppState extends State<MyApp> {
} }
``` ```
### `ContextMenu` options
* `hideDefaultSystemContextMenuItems`: Whether all the default system context menu items should be hidden or not. The default value is `false`.
### `ContextMenu` Events ### `ContextMenu` Events
* `onCreateContextMenu`: Event fired when the context menu for this WebView is being built. * `onCreateContextMenu`: Event fired when the context menu for this WebView is being built.
...@@ -1182,7 +1188,7 @@ class _MyAppState extends State<MyApp> { ...@@ -1182,7 +1188,7 @@ class _MyAppState extends State<MyApp> {
url: "https://flutter.dev/", url: "https://flutter.dev/",
options: ChromeSafariBrowserClassOptions( options: ChromeSafariBrowserClassOptions(
android: AndroidChromeCustomTabsOptions(addDefaultShareMenuItem: false), android: AndroidChromeCustomTabsOptions(addDefaultShareMenuItem: false),
ios: IosSafariOptions(barCollapsingEnabled: true))); ios: IOSSafariOptions(barCollapsingEnabled: true)));
}, },
child: Text("Open Chrome Safari Browser")), child: Text("Open Chrome Safari Browser")),
), ),
...@@ -1190,7 +1196,6 @@ class _MyAppState extends State<MyApp> { ...@@ -1190,7 +1196,6 @@ class _MyAppState extends State<MyApp> {
); );
} }
} }
``` ```
Screenshots: Screenshots:
......
...@@ -365,6 +365,17 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha ...@@ -365,6 +365,17 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
case "zoomOut": case "zoomOut":
result.success(zoomOut()); result.success(zoomOut());
break; break;
case "clearFocus":
clearFocus();
result.success(true);
break;
case "setContextMenu":
{
Map<String, Object> contextMenu = (Map<String, Object>) call.argument("contextMenu");
setContextMenu(contextMenu);
}
result.success(true);
break;
default: default:
result.notImplemented(); result.notImplemented();
} }
...@@ -909,6 +920,16 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha ...@@ -909,6 +920,16 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
return false; return false;
} }
public void clearFocus() {
if (webView != null)
webView.clearFocus();
}
public void setContextMenu(Map<String, Object> contextMenu) {
if (webView != null)
webView.contextMenu = contextMenu;
}
public void dispose() { public void dispose() {
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
activityResultListeners.clear(); activityResultListeners.clear();
......
...@@ -30,10 +30,10 @@ public class InAppBrowserOptions implements Options<InAppBrowserActivity> { ...@@ -30,10 +30,10 @@ public class InAppBrowserOptions implements Options<InAppBrowserActivity> {
switch (key) { switch (key) {
case "hidden": case "hidden":
hidden = (boolean) value; hidden = (Boolean) value;
break; break;
case "toolbarTop": case "toolbarTop":
toolbarTop = (boolean) value; toolbarTop = (Boolean) value;
break; break;
case "toolbarTopBackgroundColor": case "toolbarTopBackgroundColor":
toolbarTopBackgroundColor = (String) value; toolbarTopBackgroundColor = (String) value;
...@@ -42,16 +42,16 @@ public class InAppBrowserOptions implements Options<InAppBrowserActivity> { ...@@ -42,16 +42,16 @@ public class InAppBrowserOptions implements Options<InAppBrowserActivity> {
toolbarTopFixedTitle = (String) value; toolbarTopFixedTitle = (String) value;
break; break;
case "hideUrlBar": case "hideUrlBar":
hideUrlBar = (boolean) value; hideUrlBar = (Boolean) value;
break; break;
case "hideTitleBar": case "hideTitleBar":
hideTitleBar = (boolean) value; hideTitleBar = (Boolean) value;
break; break;
case "closeOnCannotGoBack": case "closeOnCannotGoBack":
closeOnCannotGoBack = (boolean) value; closeOnCannotGoBack = (Boolean) value;
break; break;
case "progressBar": case "progressBar":
progressBar = (boolean) value; progressBar = (Boolean) value;
break; break;
} }
} }
......
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
import com.pichillilorenzo.flutter_inappwebview.Options;
import java.util.HashMap;
import java.util.Map;
public class ContextMenuOptions implements Options<Object> {
public static final String LOG_TAG = "ContextMenuOptions";
public Boolean hideDefaultSystemContextMenuItems = false;
public ContextMenuOptions parse(Map<String, Object> options) {
for (Map.Entry<String, Object> pair : options.entrySet()) {
String key = pair.getKey();
Object value = pair.getValue();
if (value == null) {
continue;
}
switch (key) {
case "hideDefaultSystemContextMenuItems":
hideDefaultSystemContextMenuItems = (Boolean) value;
break;
}
}
return this;
}
public Map<String, Object> toMap() {
Map<String, Object> options = new HashMap<>();
options.put("hideDefaultSystemContextMenuItems", hideDefaultSystemContextMenuItems);
return options;
}
@Override
public Map<String, Object> getRealOptions(Object webView) {
Map<String, Object> realOptions = toMap();
return realOptions;
}
}
...@@ -52,8 +52,8 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -52,8 +52,8 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
final String initialFile = (String) params.get("initialFile"); final String initialFile = (String) params.get("initialFile");
final Map<String, String> initialData = (Map<String, String>) params.get("initialData"); final Map<String, String> initialData = (Map<String, String>) params.get("initialData");
final Map<String, String> initialHeaders = (Map<String, String>) params.get("initialHeaders"); final Map<String, String> initialHeaders = (Map<String, String>) params.get("initialHeaders");
HashMap<String, Object> initialOptions = (HashMap<String, Object>) params.get("initialOptions"); Map<String, Object> initialOptions = (Map<String, Object>) params.get("initialOptions");
HashMap<String, Object> contextMenu = (HashMap<String, Object>) params.get("contextMenu"); Map<String, Object> contextMenu = (Map<String, Object>) params.get("contextMenu");
InAppWebViewOptions options = new InAppWebViewOptions(); InAppWebViewOptions options = new InAppWebViewOptions();
options.parse(initialOptions); options.parse(initialOptions);
...@@ -440,6 +440,23 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { ...@@ -440,6 +440,23 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
result.success(false); result.success(false);
} }
break; break;
case "clearFocus":
if (webView != null) {
webView.clearFocus();
result.success(true);
} else {
result.success(false);
}
break;
case "setContextMenu":
if (webView != null) {
Map<String, Object> contextMenu = (Map<String, Object>) call.argument("contextMenu");
webView.contextMenu = contextMenu;
result.success(true);
} else {
result.success(false);
}
break;
default: default:
result.notImplemented(); result.notImplemented();
} }
......
...@@ -82,7 +82,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -82,7 +82,7 @@ final public class InAppWebView extends InputAwareWebView {
public Pattern regexToCancelSubFramesLoadingCompiled; public Pattern regexToCancelSubFramesLoadingCompiled;
public GestureDetector gestureDetector = null; public GestureDetector gestureDetector = null;
public LinearLayout floatingContextMenu = null; public LinearLayout floatingContextMenu = null;
public HashMap<String, Object> contextMenu = null; public Map<String, Object> contextMenu = null;
public Handler headlessHandler = new Handler(Looper.getMainLooper()); public Handler headlessHandler = new Handler(Looper.getMainLooper());
public Runnable checkScrollStoppedTask; public Runnable checkScrollStoppedTask;
...@@ -608,7 +608,7 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -608,7 +608,7 @@ final public class InAppWebView extends InputAwareWebView {
super(context, attrs, defaultStyle); super(context, attrs, defaultStyle);
} }
public InAppWebView(Context context, Object obj, Object id, InAppWebViewOptions options, HashMap<String, Object> contextMenu, View containerView) { public InAppWebView(Context context, Object obj, Object id, InAppWebViewOptions options, Map<String, Object> contextMenu, View containerView) {
super(context, containerView); super(context, containerView);
if (obj instanceof InAppBrowserActivity) if (obj instanceof InAppBrowserActivity)
this.inAppBrowserActivity = (InAppBrowserActivity) obj; this.inAppBrowserActivity = (InAppBrowserActivity) obj;
...@@ -1597,6 +1597,18 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1597,6 +1597,18 @@ final public class InAppWebView extends InputAwareWebView {
HorizontalScrollView horizontalScrollView = (HorizontalScrollView) floatingContextMenu.getChildAt(0); HorizontalScrollView horizontalScrollView = (HorizontalScrollView) floatingContextMenu.getChildAt(0);
LinearLayout menuItemListLayout = (LinearLayout) horizontalScrollView.getChildAt(0); LinearLayout menuItemListLayout = (LinearLayout) horizontalScrollView.getChildAt(0);
List<Map<String, Object>> customMenuItems = new ArrayList<>();
ContextMenuOptions contextMenuOptions = new ContextMenuOptions();
if (contextMenu != null) {
customMenuItems = (List<Map<String, Object>>) contextMenu.get("menuItems");
Map<String, Object> contextMenuOptionsMap = (Map<String, Object>) contextMenu.get("options");
if (contextMenuOptionsMap != null) {
contextMenuOptions.parse(contextMenuOptionsMap);
}
}
customMenuItems = customMenuItems == null ? new ArrayList<Map<String, Object>>() : customMenuItems;
if (contextMenuOptions.hideDefaultSystemContextMenuItems == null || !contextMenuOptions.hideDefaultSystemContextMenuItems) {
for (int i = 0; i < actionMenu.size(); i++) { for (int i = 0; i < actionMenu.size(); i++) {
final MenuItem menuItem = actionMenu.getItem(i); final MenuItem menuItem = actionMenu.getItem(i);
final int itemId = menuItem.getItemId(); final int itemId = menuItem.getItemId();
...@@ -1623,11 +1635,9 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1623,11 +1635,9 @@ final public class InAppWebView extends InputAwareWebView {
menuItemListLayout.addView(text); menuItemListLayout.addView(text);
} }
} }
}
if (contextMenu != null) { for (final Map<String, Object> menuItem : customMenuItems) {
List<HashMap<String, Object>> customMenuItems = (List<HashMap<String, Object>>) contextMenu.get("menuItems");
if (customMenuItems != null) {
for (final HashMap<String, Object> menuItem : customMenuItems) {
final int itemId = (int) menuItem.get("androidId"); final int itemId = (int) menuItem.get("androidId");
final String itemTitle = (String) menuItem.get("title"); final String itemTitle = (String) menuItem.get("title");
TextView text = (TextView) LayoutInflater.from(this.getContext()) TextView text = (TextView) LayoutInflater.from(this.getContext())
...@@ -1636,7 +1646,6 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1636,7 +1646,6 @@ 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();
hideContextMenu(); hideContextMenu();
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
...@@ -1653,8 +1662,6 @@ final public class InAppWebView extends InputAwareWebView { ...@@ -1653,8 +1662,6 @@ final public class InAppWebView extends InputAwareWebView {
} }
} }
}
}
final int x = (lastTouch != null) ? lastTouch.x : 0; final int x = (lastTouch != null) ? lastTouch.x : 0;
final int y = (lastTouch != null) ? lastTouch.y : 0; final int y = (lastTouch != null) ? lastTouch.y : 0;
......
...@@ -3,8 +3,7 @@ package com.pichillilorenzo.flutter_inappwebview; ...@@ -3,8 +3,7 @@ package com.pichillilorenzo.flutter_inappwebview;
import java.util.Map; import java.util.Map;
public interface Options<T> { public interface Options<T> {
static String LOG_TAG = "Options";
public Options parse(Map<String, Object> options); public Options parse(Map<String, Object> options);
public Map<String, Object> toMap(); public Map<String, Object> toMap();
public Map<String, Object> getRealOptions(T webView); public Map<String, Object> getRealOptions(T obj);
} }
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-29 19:53:44.213613","version":"1.17.1"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-05-30 19:55:39.840707","version":"1.17.1"}
\ No newline at end of file \ No newline at end of file
...@@ -23,6 +23,16 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -23,6 +23,16 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
super.initState(); super.initState();
contextMenu = ContextMenu( contextMenu = ContextMenu(
menuItems: [
ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async {
print("Menu item Special clicked!");
print(await webView.getSelectedText());
await webView.clearFocus();
})
],
options: ContextMenuOptions(
hideDefaultSystemContextMenuItems: true
),
onCreateContextMenu: (hitTestResult) async { onCreateContextMenu: (hitTestResult) async {
print("onCreateContextMenu"); print("onCreateContextMenu");
print(hitTestResult.extra); print(hitTestResult.extra);
...@@ -31,16 +41,11 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -31,16 +41,11 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
onHideContextMenu: () { onHideContextMenu: () {
print("onHideContextMenu"); print("onHideContextMenu");
}, },
onContextMenuActionItemClicked: (contextMenuItemClicked) { onContextMenuActionItemClicked: (contextMenuItemClicked) async {
var id = (Platform.isAndroid) ? contextMenuItemClicked.androidId : contextMenuItemClicked.iosId; var id = (Platform.isAndroid) ? contextMenuItemClicked.androidId : contextMenuItemClicked.iosId;
print("onContextMenuActionItemClicked: " + id.toString() + " " + contextMenuItemClicked.title); print("onContextMenuActionItemClicked: " + id.toString() + " " + contextMenuItemClicked.title);
} }
); );
contextMenu.menuItems = [
ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async {
print("Menu item Special clicked!");
})
];
} }
@override @override
...@@ -74,17 +79,14 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -74,17 +79,14 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
BoxDecoration(border: Border.all(color: Colors.blueAccent)), BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: InAppWebView( child: InAppWebView(
contextMenu: contextMenu, contextMenu: contextMenu,
// initialUrl: "https://github.com/flutter", initialUrl: "https://github.com/flutter",
initialFile: "assets/index.html", // initialFile: "assets/index.html",
initialHeaders: {}, initialHeaders: {},
initialOptions: InAppWebViewGroupOptions( initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions( crossPlatform: InAppWebViewOptions(
debuggingEnabled: true, debuggingEnabled: true,
useShouldOverrideUrlLoading: true useShouldOverrideUrlLoading: true
), ),
android: AndroidInAppWebViewOptions(
supportMultipleWindows: true
)
), ),
onWebViewCreated: (InAppWebViewController controller) { onWebViewCreated: (InAppWebViewController controller) {
webView = controller; webView = controller;
......
//
// ContextMenuOptions.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 30/05/2020.
//
import Foundation
class ContextMenuOptions: Options<NSObject> {
var hideDefaultSystemContextMenuItems = false;
override init(){
super.init()
}
}
...@@ -426,6 +426,23 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor ...@@ -426,6 +426,23 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
result(nil) result(nil)
} }
break break
case "clearFocus":
if webView != nil {
webView!.clearFocus()
result(true)
} else {
result(false)
}
break
case "setContextMenu":
if webView != nil {
let contextMenu = arguments!["contextMenu"] as? [String: Any]
webView!.contextMenu = contextMenu
result(true)
} else {
result(false)
}
break
default: default:
result(FlutterMethodNotImplemented) result(FlutterMethodNotImplemented)
break break
......
...@@ -308,6 +308,24 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS ...@@ -308,6 +308,24 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS
result(nil) result(nil)
} }
break break
case "clearFocus":
if webView != nil {
webView!.clearFocus()
result(true)
} else {
result(false)
}
break
case "setContextMenu":
if webView != nil {
let contextMenu = arguments!["contextMenu"] as? [String: Any]
webView!.contextMenu = contextMenu
result(true)
} else {
result(false)
}
break
default: default:
result(FlutterMethodNotImplemented) result(FlutterMethodNotImplemented)
break break
......
...@@ -905,6 +905,16 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi ...@@ -905,6 +905,16 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
return false return false
} }
if let menu = contextMenu {
let contextMenuOptions = ContextMenuOptions()
if let contextMenuOptionsMap = menu["options"] as? [String: Any?] {
let _ = contextMenuOptions.parse(options: contextMenuOptionsMap)
if !action.description.starts(with: "onContextMenuActionItemClicked-") && contextMenuOptions.hideDefaultSystemContextMenuItems {
return false
}
}
}
if contextMenuIsShowing, !action.description.starts(with: "onContextMenuActionItemClicked-") { if contextMenuIsShowing, !action.description.starts(with: "onContextMenuActionItemClicked-") {
let id = action.description.compactMap({ $0.asciiValue?.description }).joined() let id = action.description.compactMap({ $0.asciiValue?.description }).joined()
let arguments: [String: Any?] = [ let arguments: [String: Any?] = [
...@@ -2729,6 +2739,10 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi ...@@ -2729,6 +2739,10 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
} }
} }
public func clearFocus() {
self.scrollView.subviews.first?.resignFirstResponder()
}
public func dispose() { public func dispose() {
stopLoading() stopLoading()
configuration.userContentController.removeScriptMessageHandler(forName: "consoleLog") configuration.userContentController.removeScriptMessageHandler(forName: "consoleLog")
......
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter_inappwebview/src/webview.dart';
import 'webview.dart';
import 'types.dart'; import 'types.dart';
///Class that represents the WebView context menu. It used by [WebView.contextMenu]. ///Class that represents the WebView context menu. It used by [WebView.contextMenu].
...@@ -22,24 +22,35 @@ class ContextMenu { ...@@ -22,24 +22,35 @@ class ContextMenu {
final void Function(ContextMenuItem contextMenuItemClicked) final void Function(ContextMenuItem contextMenuItemClicked)
onContextMenuActionItemClicked; onContextMenuActionItemClicked;
///Context menu options.
final ContextMenuOptions options;
///List of the custom [ContextMenuItem]. ///List of the custom [ContextMenuItem].
List<ContextMenuItem> menuItems = List(); final List<ContextMenuItem> menuItems;
ContextMenu( ContextMenu(
{this.menuItems, {this.menuItems = const [],
this.onCreateContextMenu, this.onCreateContextMenu,
this.onHideContextMenu, this.onHideContextMenu,
this.onContextMenuActionItemClicked}); this.options,
this.onContextMenuActionItemClicked})
: assert(menuItems != null);
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
"menuItems": menuItems.map((menuItem) => menuItem?.toMap()).toList() "menuItems": menuItems.map((menuItem) => menuItem?.toMap()).toList(),
"options": options?.toMap()
}; };
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return this.toMap(); return this.toMap();
} }
@override
String toString() {
return toMap().toString();
}
} }
///Class that represent an item of the [ContextMenu]. ///Class that represent an item of the [ContextMenu].
...@@ -69,4 +80,32 @@ class ContextMenuItem { ...@@ -69,4 +80,32 @@ class ContextMenuItem {
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return this.toMap(); return this.toMap();
} }
@override
String toString() {
return toMap().toString();
}
}
///Class that represents available options used by [ContextMenu].
class ContextMenuOptions {
///Whether all the default system context menu items should be hidden or not. The default value is `false`.
bool hideDefaultSystemContextMenuItems;
ContextMenuOptions({this.hideDefaultSystemContextMenuItems = false});
Map<String, dynamic> toMap() {
return {
"hideDefaultSystemContextMenuItems": hideDefaultSystemContextMenuItems
};
}
Map<String, dynamic> toJson() {
return this.toMap();
}
@override
String toString() {
return toMap().toString();
}
} }
...@@ -13,10 +13,10 @@ import 'types.dart'; ...@@ -13,10 +13,10 @@ import 'types.dart';
///This class uses the native WebView of the platform. ///This class uses the native WebView of the platform.
///The [webViewController] field can be used to access the [InAppWebViewController] API. ///The [webViewController] field can be used to access the [InAppWebViewController] API.
class InAppBrowser { class InAppBrowser {
///Browser's UUID ///Browser's UUID.
String uuid; String uuid;
///Context menu used by the browser ///Context menu used by the browser. It should be set before opening the browser.
ContextMenu contextMenu; ContextMenu contextMenu;
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap = Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
......
...@@ -1487,6 +1487,23 @@ class InAppWebViewController { ...@@ -1487,6 +1487,23 @@ class InAppWebViewController {
return InAppWebViewHitTestResult(type: type, extra: extra); return InAppWebViewHitTestResult(type: type, extra: extra);
} }
///Clears the current focus. It will clear also, for example, the current text selection.
///
///**Official Android API**: https://developer.android.com/reference/android/view/ViewGroup#clearFocus()
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiresponder/1621097-resignfirstresponder
Future<void> clearFocus() async {
Map<String, dynamic> args = <String, dynamic>{};
return await _channel.invokeMethod('clearFocus', args);
}
///Sets or updates the WebView context menu to be used next time it will appear.
Future<void> setContextMenu(ContextMenu contextMenu) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("contextMenu", () => contextMenu?.toMap());
await _channel.invokeMethod('setContextMenu', args);
_inAppBrowser?.contextMenu = contextMenu;
}
///Gets the default user agent. ///Gets the default user agent.
/// ///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebSettings#getDefaultUserAgent(android.content.Context) ///**Official Android API**: https://developer.android.com/reference/android/webkit/WebSettings#getDefaultUserAgent(android.content.Context)
...@@ -1617,6 +1634,14 @@ class AndroidInAppWebViewController { ...@@ -1617,6 +1634,14 @@ class AndroidInAppWebViewController {
return await _controller._channel.invokeMethod('zoomOut', args); return await _controller._channel.invokeMethod('zoomOut', args);
} }
///Clears the internal back/forward list.
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#clearHistory()
Future<void> clearHistory() async {
Map<String, dynamic> args = <String, dynamic>{};
return await _controller._channel.invokeMethod('clearHistory', args);
}
///Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests. ///Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests.
///Note that WebView automatically clears these preferences when the system keychain is updated. ///Note that WebView automatically clears these preferences when the system keychain is updated.
///The preferences are shared by all the WebViews that are created by the embedder application. ///The preferences are shared by all the WebViews that are created by the embedder application.
......
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