Skip to content

Commit 996ce57

Browse files
authored
Merge pull request #1 from flickerlist/flicker-master-2
Support keyboardDisplayRequiresUserAction to focus automaticlly in iOS
2 parents 683d1ca + 811f2f2 commit 996ce57

18 files changed

Lines changed: 129 additions & 16 deletions

File tree

dev_packages/generators/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ version: 1.0.0
44
publish_to: none
55

66
environment:
7-
sdk: ^3.5.0
8-
flutter: ">=3.24.0"
7+
sdk: ">=3.4.0"
8+
flutter: ">=3.22.3"
99

1010
dependencies:
1111
flutter:

flutter_inappwebview/lib/src/in_app_webview/in_app_webview_controller.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@ class InAppWebViewController {
290290
Future<InAppWebViewHitTestResult?> getHitTestResult() =>
291291
platform.getHitTestResult();
292292

293+
///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.requestFocus}
294+
Future<void> requestFocus() => platform.requestFocus();
295+
293296
///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.clearFocus}
294297
Future<void> clearFocus() => platform.clearFocus();
295298

flutter_inappwebview/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ topics:
1414
- browser
1515

1616
environment:
17-
sdk: ^3.5.0
18-
flutter: ">=3.24.0"
17+
sdk: ^3.4.0
18+
flutter: ">=3.22.3"
1919

2020
dependencies:
2121
flutter:

flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegate.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,12 @@ public void onReceiveValue(String value) {
468468
result.success(false);
469469
}
470470
break;
471+
case requestFocus:
472+
if (webView != null) {
473+
webView.requestFocus();
474+
}
475+
result.success(true);
476+
break;
471477
case clearFocus:
472478
if (webView != null) {
473479
webView.clearFocus();

flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegateMethods.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public enum WebViewChannelDelegateMethods {
6262
saveWebArchive,
6363
zoomIn,
6464
zoomOut,
65+
requestFocus,
6566
clearFocus,
6667
setContextMenu,
6768
requestFocusNodeHref,

flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InputAwareWebView.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ public boolean checkInputConnectionProxy(final View view) {
150150
public void clearFocus() {
151151
super.clearFocus();
152152

153+
InputMethodManager inputManager = (InputMethodManager) this.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
154+
if (inputManager != null) {
155+
inputManager.hideSoftInputFromWindow(this.getWindowToken(), 0);
156+
}
157+
153158
if (useHybridComposition) {
154159
return;
155160
}

flutter_inappwebview_android/lib/src/in_app_webview/in_app_webview_controller.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,6 +2241,12 @@ class AndroidInAppWebViewController extends PlatformInAppWebViewController
22412241
return InAppWebViewHitTestResult(type: type, extra: extra);
22422242
}
22432243

2244+
@override
2245+
Future<void> requestFocus() async {
2246+
Map<String, dynamic> args = <String, dynamic>{};
2247+
return await channel?.invokeMethod('requestFocus', args);
2248+
}
2249+
22442250
@override
22452251
Future<void> clearFocus() async {
22462252
Map<String, dynamic> args = <String, dynamic>{};

flutter_inappwebview_android/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ topics:
1414
- browser
1515

1616
environment:
17-
sdk: ^3.5.0
18-
flutter: ">=3.24.0"
17+
sdk: ">=3.4.0"
18+
flutter: ">=3.22.3"
1919

2020
dependencies:
2121
flutter:

flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,75 @@ import Flutter
99
import Foundation
1010
import WebKit
1111

12+
// Support `keyboardDisplayRequiresUserAction` to focus automaticlly
13+
typealias OldClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Any?) -> Void
14+
typealias NewClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void
15+
extension WKWebView{
16+
var keyboardDisplayRequiresUserAction: Bool? {
17+
get {
18+
return self.keyboardDisplayRequiresUserAction
19+
}
20+
set {
21+
self.setKeyboardRequiresUserInteraction(newValue ?? true)
22+
}
23+
}
24+
25+
func setKeyboardRequiresUserInteraction( _ value: Bool) {
26+
guard let WKContentView: AnyClass = NSClassFromString("WKContentView") else {
27+
print("keyboardDisplayRequiresUserAction extension: Cannot find the WKContentView class")
28+
return
29+
}
30+
// For iOS 10, *
31+
let sel_10: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:userObject:")
32+
// For iOS 11.3, *
33+
let sel_11_3: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:")
34+
// For iOS 12.2, *
35+
let sel_12_2: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:")
36+
// For iOS 13.0, *
37+
let sel_13_0: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:")
38+
39+
if let method = class_getInstanceMethod(WKContentView, sel_10) {
40+
let originalImp: IMP = method_getImplementation(method)
41+
let original: OldClosureType = unsafeBitCast(originalImp, to: OldClosureType.self)
42+
let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3) in
43+
original(me, sel_10, arg0, !value, arg2, arg3)
44+
}
45+
let imp: IMP = imp_implementationWithBlock(block)
46+
method_setImplementation(method, imp)
47+
}
48+
49+
if let method = class_getInstanceMethod(WKContentView, sel_11_3) {
50+
let originalImp: IMP = method_getImplementation(method)
51+
let original: NewClosureType = unsafeBitCast(originalImp, to: NewClosureType.self)
52+
let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3, arg4) in
53+
original(me, sel_11_3, arg0, !value, arg2, arg3, arg4)
54+
}
55+
let imp: IMP = imp_implementationWithBlock(block)
56+
method_setImplementation(method, imp)
57+
}
58+
59+
if let method = class_getInstanceMethod(WKContentView, sel_12_2) {
60+
let originalImp: IMP = method_getImplementation(method)
61+
let original: NewClosureType = unsafeBitCast(originalImp, to: NewClosureType.self)
62+
let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3, arg4) in
63+
original(me, sel_12_2, arg0, !value, arg2, arg3, arg4)
64+
}
65+
let imp: IMP = imp_implementationWithBlock(block)
66+
method_setImplementation(method, imp)
67+
}
68+
69+
if let method = class_getInstanceMethod(WKContentView, sel_13_0) {
70+
let originalImp: IMP = method_getImplementation(method)
71+
let original: NewClosureType = unsafeBitCast(originalImp, to: NewClosureType.self)
72+
let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3, arg4) in
73+
original(me, sel_13_0, arg0, !value, arg2, arg3, arg4)
74+
}
75+
let imp: IMP = imp_implementationWithBlock(block)
76+
method_setImplementation(method, imp)
77+
}
78+
}
79+
}
80+
1281
public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
1382
WKNavigationDelegate, WKScriptMessageHandler, UIGestureRecognizerDelegate,
1483
WKDownloadDelegate,
@@ -81,6 +150,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
81150
}
82151
self.contextMenu = contextMenu
83152
self.initialUserScripts = userScripts
153+
self.keyboardDisplayRequiresUserAction = false
84154
uiDelegate = self
85155
navigationDelegate = self
86156
scrollView.delegate = self
@@ -3138,6 +3208,10 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
31383208
}
31393209
}
31403210

3211+
public func requestFocus() {
3212+
self.scrollView.subviews.first?.becomeFirstResponder()
3213+
}
3214+
31413215
public func clearFocus() {
31423216
self.scrollView.subviews.first?.resignFirstResponder()
31433217
}

flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegate.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,10 @@ public class WebViewChannelDelegate: ChannelDelegate {
344344
result(nil)
345345
}
346346
break
347+
case .requestFocus:
348+
webView?.requestFocus()
349+
result(true)
350+
break
347351
case .clearFocus:
348352
webView?.clearFocus()
349353
result(true)

0 commit comments

Comments
 (0)