react-native-webview / react-native-webview

React Native Cross-Platform WebView
https://github.com/react-native-community/discussions-and-proposals/pull/3
MIT License
6.52k stars 2.99k forks source link

.focus() doesn't work in Android #1172

Closed Jakuubzmeko closed 4 years ago

Jakuubzmeko commented 4 years ago

Bug description: I am using react native rich text editor on both android and iOS. It uses webview component and it gets some javascript as a source. In the javascript I have defined some html and there ist a div, which is editable. By selecting this div and calling .focus() funcion I can focus it only on iOS not on Android and that's the problem, that after calling focus() in android id doesn't focus and doesn't show keyboard

To Reproduce: I am using this rich text editor: https://github.com/stulip/react-native-pell-rich-editor

Expected behavior: when I call .focus() in js, the div should be focused and show keyboard in android

Environment:

sgtpepper43 commented 4 years ago

I'm having the same problem. There is a requestFocus you can call on the webview itself that should work, but, at least for me it's not working.

ovistoica commented 4 years ago

We also have the same problem. We did a workaround where we put above the editor a TextInput as a title which is initially focused but when we change focus from the React Native TextInput to the Webview from pell-rich-editor, they keyboard just dismisses. We also wrapped everything in a scrollview with keyboardShouldPersistTaps={'always'} and keyboardDismissMode={'none'} but it didn't fix the problem

Nice-zrd commented 4 years ago

I tried to call requestFocus in the onLoad method, which is not easy to use, but I put it in setTimeout and gave it a 100 millisecond delay to solve Android's focus.

if (Platform.OS != 'ios') { setTimeout(() => { webView.requestFocus(); }, 100); }

But there are new problems. Android does not actively pop up the keyboard after obtaining WebView focus through requestfocus. I can't solve this problem now.

Nice-zrd commented 4 years ago

We also have the same problem. We did a workaround where we put above the editor a TextInput as a title which is initially focused but when we change focus from the React Native TextInput to the Webview from pell-rich-editor, they keyboard just dismisses. We also wrapped everything in a scrollview with keyboardShouldPersistTaps={'always'} and keyboardDismissMode={'none'} but it didn't fix the problem

I have the same problem as you. When you switch the cursor from Textinput to webView, the keyboard will be hidden. You need to click WebView again to pop up the keyboard and wait for the problem to be solved.

Nantris commented 4 years ago

Is it theoretically possible to make this work? Or will Android refuse to open the keyboard and that's beyond our control?

rmanalo-getdevs commented 4 years ago

i'm having the same problem

AndreySierra commented 4 years ago

Please solve this :(

rojo2530 commented 4 years ago

Yes, in IOS work OK, but not in Android.

oleksandr-dziuban commented 4 years ago

Same issue, but I'm using QuillJS Rich Text Editor with WebView. It also uses editable div and I try to request focus on it programmatically with .focus(). On WEB version of our app it works fine. On iOS too. But Android performs selection of the text only. Keyboard is not appeared. Need additionally to click on WebView and whole text selection will be activated as expected. I think the problem just in ability to open keyboard from WebView programmatically on Android. Maybe we need to activate some permissions for Android xml configs? Same as we use keyboardDisplayRequiresUserAction={false} props to allow iOS to focus programmatically. Could someone please check this issue in this cool library? Thanks a lot

jamonholmgren commented 4 years ago

We'd love some help solving this issue from the community. Post a link to the PR here if you submit one. Thank you!

jamonholmgren commented 4 years ago

Oops, didn't mean to close this.

stulip commented 4 years ago

@stoica94 @Jakuubzmeko @Nice-zrd pell-rich-editor publish 1.0.9-beta.0 Based on the 1.0.8 experimental processing method(Android only)

https://github.com/stulip/react-native-pell-rich-editor/commit/db17f73bd1d5db6540d03ec0615b0d2c8fddfe3e

Can refer topell-rich-editor example

Nantris commented 4 years ago

The pell-rich method can only work in non-Expo apps, as Expo can't control keyboard visibility.

stulip commented 4 years ago

The pell-rich method can only work in non-Expo apps, as Expo can't control keyboard visibility.

@Slapbox 1.0.9-beta.1 fix Expo android keyboard open

Environment:

Nantris commented 4 years ago

I haven't given it a test, but wow that's crazy!

How did you manage that @wxik? I took a look at the code here, but I don't quite understand how works.

Thanks so much for sharing!

stulip commented 4 years ago

@Slapbox

A TextInput of size 1 and invisible is used, the TextInput Keyboard of focus will be opened, and then the focus in the webview is triggered, at this time the keyboard will remain open

Nantris commented 4 years ago

@stulip thanks for the explanation!

If I understand correctly, it's not that Android users can't focus the webview, it's just that the focusing of the webview doesn't trigger the keyboard to show? I won't get to give this a try for a while, but I'm excited. Thanks again for sharing!

github-actions[bot] commented 4 years ago

Hello 👋, this issue has been opened for more than 2 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically

Nantris commented 4 years ago

Not stale.

ammarahm-ed commented 4 years ago

You need to manually open the keyboard after the input is focused on android. It cannot be done automatically. A simple method on Native Side can do this probably.

public static void showKeyboard(FragmentActivity activity) {
        InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputMethodManager.toggleSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), InputMethodManager.SHOW_FORCED, 0);
    }

Its not optimised for React Native but that is how it will work, I once tried while I had a project where I was using Quill as an editor inside the WebView.

Nantris commented 4 years ago

@ammarahm-ed thanks for sharing! That seems very useful, but it's not something Expo users can leverage. It would be great if this was built into React Native Webview.

zaiisao commented 3 years ago

I want to leave a comment here to write about my own approach to solving this problem, and although it is quite hacky, it seems to work like a charm.

  1. In the component with the WebView, also put in a TextInput with autoFocus set to true
  2. In componentDidMount, call requestFocus on the WebView component
  3. When onLoad of the WebView component is fired, get the rich text editor (I'm using QuillJS) to focus (in my case, QuillJS's focus function) to focus with postMessage triggering the HTML page to do so
  4. Get another message sent back to React Native once focusing is applied
  5. Set a boolean in the component's state that would cause the TextInput with autoFocus = true to be removed

I'm treating this solution with a grain of salt, but it seems to work. The temporary TextInput kicks the keyboard open, and from there we can switch the focus to the WebView component with the rich text editor input already focused, and everything seems to work like a charm. I'm still going to be treating this solution with a grain of salt in case if anything weird happens in the future, but this allowed me to be able to solve the problem without digging into Java.

hongquan281096 commented 3 years ago

Dear everyone, I'm having the same issue. I need your helppppppppppppppppppppp!!!. I work on Expo CLI

chinhlt commented 3 years ago

I can fixed this issue on Android. I am use that rich text for edit html, toolbar with action foreColor to set text color. When click on action foreColor, I used: richText.current?.blurContentEditor(); => to dismiss web keyboard. setTimeout(() => { setIShowModalColor(true); => to open color picker modal }, 100); => must delay Then selected color from modal: setIShowModalColor(false); => hide modal setTimeout(() => { richText.current?.focusContentEditor(); => focus web input richText.current?.setForeColor(selectedHTMLColor); }, 100); => must delay => And on Android keyboard auto focus and open OK. setTimeout 100 is working.

arunim2405 commented 2 years ago

This should be neither stale nor closed, this is still very much an issue

realityexpander commented 2 years ago

Here is the workaround solution I came up with based on zaiiso's suggestions:

// in TextEditor.tsx component

    const webviewRef = useRef<WebView>(null);
    const [isKeyboardVisible, setIsKeyboardVisible] = useState<boolean>(false);
    const [isTextEditorLoadCompleted, setIsTextEditorLoadCompleted] = useState<boolean>(false);

useEffect(() => {
        // focus on the webview to show keyboard on Android
        if (Platform.OS === 'android') {
            if (webviewRef.current) webviewRef.current.requestFocus();
        }
    }, []);

 useEffect(() => {
        const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
            setIsKeyboardVisible(true);
            setIsTextEditorLoadCompleted(true);
        });
        const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
            setIsKeyboardVisible(false);
        });

        return () => {
            keyboardDidHideListener.remove();
            keyboardDidShowListener.remove();
        };
    }, []);

    // Workaround to get keyboard to show when TextEditor is opened (on Android.)
    // - This is a currently a hack, but it works for now.
    // - Issue is officially "closed" on react-native-webview, but was not fixed/resolved. *shrug*
    // - https://github.com/react-native-webview/react-native-webview/issues/1172#issuecomment-810219790
    const showKeyboardOnAndroidWorkaround =
        Platform.OS === 'android'
            ? !isTextEditorLoadCompleted && (
                  <TextInput
                      autoFocus={true}
                      style={{
                          display: 'none',
                          width: 0,
                          height: 0,
                          position: 'absolute',
                          flex: 1,
                          top: 0,
                          left: 0,
                      }}
                  />
              )
            : null;

    return (
        <View style={[{flex: 1}, animatedStyles]}>
            {showKeyboardOnAndroidWorkaround}
            <WebView
                key={'TextEditor'}
                allowFileAccessFromFileURLs={true}
                ref={webviewRef}
                automaticallyAdjustContentInsets={true}
                source={{html: textEditorHTML}}
                bounces={false}
                overScrollMode="never"
                style={[{backgroundColor: 'transparent', maxHeight: 510}]}
                originWhitelist={['*']}
            />
        </View>