Search code examples
androidreact-nativereact-native-textinput

React Native TextInput color issue in fullscreen landscape mode


I have a simple TextInput in my react-native Android app. And it opens as fullscreen when focused in landscape mode. However in the fullscreen keyboard mode, both the background and foreground is white, therefore I can't see the text I'm typing:

enter image description here

The TextInput looks normal when it is not focused:

enter image description here

And this is the related code:

<TextInput
    onChangeText={this.changeText}
    value={text}
    disableFullscreenUI={false}  />

I can give it a style with black color, however in that case black color won't be visible because the TextInput is in a dark screen as you can see above. So this needs a solution like giving two colors changing on focus and blur but that really should not be the way to use TextInput.

The same issue has been posted here and here. It's mentioned that this is fixed with react-native's versions above 0.50. However I'm already using 0.63.3 and the issue is still there.

Has anyone encountered this issue? Any help would be appreciated, thanks!


Solution

  • After struggling with this for a day, I have found a workaround. This does not actually fix the bug, but it's a small "hack" that hides the bug. However, the bug still exists with react-native's latest version. So here is a brief explanation of the bug, why some solutions don't work and how I overcame it:

    TextInput inherits the applied color style in its native fullscreen editor view, whereas it should not. The native fullscreen always opens with a white background. Imagine you have a TextInput in a dark screen in your app, then you most probably have a white font color. The problem happens right in this case, the fullscreen editor opens with a white font over a white background.

    • The first thing comes to mind is applying a black font color. However this leads to having a black color in your dark screen as well. So it's obvious that two colors should be applied changing dynamically.
    • Detecting the keyboard events, applying dark color when keyboard is shown, and applying light color when keyboard is hidden would be a good idea. However, keyboardDidShow and keyboardDidHide events are NOT fired when TextInput is used with disableFullscreenUI prop. That's very strange but yes it's another bug and they are simply not fired. I can confirm this by removing the prop and seeing they are fired again.
    • Applying different colors in focused/blurred states would be another solution in theory. However this is leading to much more complication. Going back from the editor with back button, the input is still on focused state, and there you have to use onTouch events and it will become a never ending loop. So definitely this is not a solution in practice.

    Note: This bug also does not exist on secureTextEntry TextInputs. Interestingly, TextInputs with secureTextEntry do not inherit the color style in fullscreen mode.

    The solution

    The workaround is conditionally placing a Text component over the TextInput, and hiding the TextInput. This way, it is possible to give different colors for the fullscreen keyboard editor, and the text displayed.

    So first write a simple method that detects if the app is in landscape orientation, disableFullscreenUI is false and it's not a secure text entry.

    const isFullscreenKeyboardEnabled = () =>
       props.orientation === LANDSCAPE // Write your own logic of orientation
       && props.disableFullscreenUI === false
       && !props.secureTextEntry
    

    Add a dummy Text with an absolute position and white font color before the TextInput. It should come before TextInput because user should still be able to interact with the TextInput by clicking on it.

    {isFullscreenKeyboardEnabled() &&
        <Text style={styles.textInputOverlay}>{text}</Text>}
    

    Modify the TextInput's style. In fullscreen mode, it should simple have a zero opacity and black font color.

    <TextInput
        value={text}
        disableFullscreenUI={props.disableFullscreenUI}
        style={[
            styles.textInput, isFullscreenKeyboardEnabled() && styles.textInputFullscreen
        ]}/>
    

    This way, user will see the white text in the screen, click on it and open the fullscreen editor with black font. The trick is hiding the TextInput with black font on dark screen as above. So I hope this solution helps anyone encountering the same issue.