I'm looking for a way to auto focus an input / textarea field OR trigger a tap inside of a WebView component in React Native. The goal behind autofocus is to make sure the keyboard pops-up right away...
Does anyone have any ideas? Tips to open or close the keyboard are also useful...
I also filed an issue here: https://github.com/facebook/react-native/issues/18965
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
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With