React-native: iOS 14 Only: KeyboardAvoidingView resets to full height upon any screen press, even if the keyboard remains active

Created on 17 Sep 2020  路  8Comments  路  Source: facebook/react-native

Hi all. This is an issue I am experiencing only on devices running iOS 14.

If a user clicks into a TextInput the keyboard appears and KeyboardAvoidingView adjusts my UI. If the user clicks anywhere on the screen (a blank view, text view, pressable, etc), the KeyboardAvoidingView immediately adjusts as if the keyboard has been dismissed, even though the keyboard remains on the screen (as it should). In other words, KeyboardAvoidingView is resetting to the no-keyboard state any time the screen is pressed.

React Native version:

System: OS: macOS 10.15.6 CPU: (4) x64 Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz Memory: 1.53 GB / 8.00 GB Shell: 5.7.1 - /bin/zsh Binaries: Node: 12.16.1 - /usr/local/bin/node Yarn: Not Found npm: 6.13.4 - /usr/local/bin/npm Watchman: 4.9.0 - /opt/local/bin/watchman Managers: CocoaPods: 1.9.0 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: iOS 13.4, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2 Android SDK: Not Found IDEs: Android Studio: Not Found Xcode: 11.4/11E146 - /usr/bin/xcodebuild Languages: Java: Not Found Python: 2.7.16 - /usr/bin/python npmPackages: @react-native-community/cli: ^4.13.0 => 4.13.0 react: 16.13.1 => 16.13.1 react-native: ^0.63.0 => 0.63.0 react-native-macos: Not Found npmGlobalPackages: *react-native*: Not Found

Steps To Reproduce

Reproduction in progress

There is a workaround/hacky fix available (see below)

Keyboard KeyboardAvoidingView Needs iOS

Most helpful comment

I seem to be having the same issue but in my case the UI does not readjust after the keyboard is dismissed.

All 8 comments

I seem to be having the same issue but in my case the UI does not readjust after the keyboard is dismissed.

This is a workaround that I have been using

I've managed to patch the issue by making my own KeyboardAvoidingView. While the animation and responsiveness can be slow at time (since I'm not using native driver), it at least works as expected.

To put it simply:
````
class ... extends React.Component {
Height = new Animated.Value(0);

componentDidMount() {
    const animateTo = (y, duration) => Animated.timing(this.Height, {toValue:y, duration, useNativeDriver:false}).start();

    Keyboard.addListener("keyboardWillShow", evt => {animateTo(evt.endCoordinates.height, evt.duration)});
    Keyboard.addListener("keyboardWillHide", evt => {animateTo(0, evt.duration)});
    Keyboard.addListener("keyboardWillShow", evt => {animateTo(evt.endCoordinates.height, evt.duration)});
}

render() {
    return <React.Fragment>
        {this.props.children}
        <Animated.View style={{height:this.Height}}/>
    </React.Fragment>;
}

// (for simplicity I haven't included removing the listeners, etc)

}
````

The main differences are that I am listening to keyboardWillShow, keyboardWillHide, and keyboardWillChangeFrame; whereas KAV listens only to keyboardWillChangeFrame on iOS and keyboardDidShow and keyboardDidHide on Android. I also do not have anything like this line which sets height to 0 if the event is null:

https://github.com/facebook/react-native/blob/18f29db5a765b1e3523773aad8301c0e7e52ab9a/Libraries/Components/Keyboard/KeyboardAvoidingView.js#L110

I'm having the exactly same issue. 馃槺馃槺馃槺

I am having Keyboard issues but on users upgrading to Android 11.

I've managed to get a workaround by making my own KeyboardAvoidingView. While the animation and responsiveness can be slow at time (since I'm not using native driver), it at least works as expected.

To put it simply:

class ... extends React.Component {
    Height = new Animated.Value(0);

    componentDidMount() {
        const animateTo = (y, duration) => Animated.timing(this.Height, {toValue:y, duration, useNativeDriver:false}).start();

        Keyboard.addListener("keyboardWillShow", evt => {animateTo(evt.endCoordinates.height, evt.duration)});
        Keyboard.addListener("keyboardWillHide", evt => {animateTo(0, evt.duration)});
        Keyboard.addListener("keyboardWillShow", evt => {animateTo(evt.endCoordinates.height, evt.duration)});
    }

    render() {
        return <React.Fragment>
            {this.props.children}
            <Animated.View style={{height:this.Height}}/>
        </React.Fragment>;
    }

    // (for simplicity I haven't included removing the listeners, etc)
}

The main differences are that I am listening to keyboardWillShow, keyboardWillHide, and keyboardWillChangeFrame; whereas KAV listens only to keyboardWillChangeFrame on iOS and keyboardDidShow and keyboardDidHide on Android. I also do not have anything like this line which sets height to 0 if the event is null:

https://github.com/facebook/react-native/blob/18f29db5a765b1e3523773aad8301c0e7e52ab9a/Libraries/Components/Keyboard/KeyboardAvoidingView.js#L110

The listeners are not firing in my case :/

Hi @wmonecke,

My solution only addresses the issue on iOS. I think the listeners are different on Android.

The React Native KeyboardAvoidingView library uses keyboardDidShow and keyboardDidHide (did instead of will). You can try using those events instead, but I think your issue may be a separate one.

Seems to be better with behaviour set to padding instead of height

Do we have any updates from React Native maintainers? Seems like a lot of people are experiencing this with no good workaround yet.

Was this page helpful?
0 / 5 - 0 ratings