How to focus a <WebView> in react native?
See https://facebook.github.io/react-native/docs/webview.html#injectedjavascript
You can execute any javascript on WebView page
let injectScript = `document.querySelector('#myInput').focus();`;
<WebView
injectedJavaScript={injectScript}
source={{uri:"XXX"}}
startInLoadingState
/>
UPDATE: Since I posted this, someone created this module that has "autofocus": https://github.com/TryImpossible/react-native-enhance-webview (for solution 2)
After researching this a bit I see 2 solutions for this.
- Fork React Native and adjust the WebView component.
The following changes to get a WebView focused need to be applied to https://github.com/facebook/react-native/blob/6e359c4589b0627de59332ce56fe28804425a609/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java#L545
view.loadUrl(url, headerMap);
view.requestFocus();
return;
The added view.requestFocus(); will give focus to the WebView. After that in the WebView you need to call .focus()
on some HTML element.
- Second solution is to write a custom native component based on the WebView, this is a simpler solution because forking and rebuilding React Native is a bit of work...
Best resources to help with this solution is to follow these two articles:
https://lakshinkarunaratne.wordpress.com/2018/01/22/enhancing-the-react-native-webview-part-1-supporting-file-uploads-in-ios-android/
https://lakshinkarunaratne.wordpress.com/2018/03/11/enhancing-the-react-native-webview-part-2-supporting-file-downloads-in-android/
The most important file in the native component is the AdvancedWebviewManager.java
. In there you can override or define a new source
method that will call .requestFocus()
after loading the URL:
package your.package.advancedwebview;
import android.webkit.WebView;
import javax.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.webview.ReactWebViewManager;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;
public class AdvancedWebviewManager extends ReactWebViewManager {
public WebView webview = null;
public static final String REACT_CLASS = "AdvancedWebview";
private AdvancedWebviewPackage aPackage;
public String getName() {
return REACT_CLASS;
}
@ReactProp(name = "sourceFocus")
public void setSource(WebView view, @Nullable ReadableMap source) {
if (source != null) {
if (source.hasKey("html")) {
String html = source.getString("html");
if (source.hasKey("baseUrl")) {
view.loadDataWithBaseURL(
source.getString("baseUrl"), html, HTML_MIME_TYPE, HTML_ENCODING, null);
} else {
view.loadData(html, HTML_MIME_TYPE, HTML_ENCODING);
}
return;
}
if (source.hasKey("uri")) {
String url = source.getString("uri");
String focusKeyboard = source.getString("focusKeyboard");
String previousUrl = view.getUrl();
if (previousUrl != null && previousUrl.equals(url)) {
return;
}
if (source.hasKey("method")) {
String method = source.getString("method");
if (method.equals(HTTP_METHOD_POST)) {
byte[] postData = null;
if (source.hasKey("body")) {
String body = source.getString("body");
try {
postData = body.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
postData = body.getBytes();
}
}
if (postData == null) {
postData = new byte[0];
}
view.postUrl(url, postData);
return;
}
}
HashMap<String, String> headerMap = new HashMap<>();
if (source.hasKey("headers")) {
ReadableMap headers = source.getMap("headers");
ReadableMapKeySetIterator iter = headers.keySetIterator();
while (iter.hasNextKey()) {
String key = iter.nextKey();
if ("user-agent".equals(key.toLowerCase(Locale.ENGLISH))) {
if (view.getSettings() != null) {
view.getSettings().setUserAgentString(headers.getString(key));
}
} else {
headerMap.put(key, headers.getString(key));
}
}
}
view.loadUrl(url, headerMap);
if (focusKeyboard.equals("focus")) {
view.requestFocus();
}
return;
}
}
view.loadUrl(BLANK_URL);
}
public void setPackage(AdvancedWebviewPackage aPackage){
this.aPackage = aPackage;
}
public AdvancedWebviewPackage getPackage(){
return this.aPackage;
}
}
This basically copies and extends the ReactWebViewManager.java
file from: https://github.com/facebook/react-native/blob/6e359c4589b0627de59332ce56fe28804425a609/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java#L545
In latest versions of react-native-webview
, WebView got method requestFocus()
. It's undocumented yet, so use with caution.
I was also looking for a solution, and it works well on Android.
https://github.com/react-native-community/react-native-webview/commit/6f053bad7be666d09b49e403931656d6b4fa410a#diff-bad447a30759e328812e9bae6798621cR21