A modern, developer friendly React Native keyboard avoiding solution that actually works how it is supposed too all of the time and provides consistency across platforms. Provides a higher quality user experience and developer experience out of the box.
- Consistent cross platform behavior by default
 - More responsive scroll view
- Section based scrolling (show entire section when keyboard visible)
 
 - Multiple behaviors that work with any layout
 - Compatible with Expo
 - Avoids pitfalls of similar libraries that lead to bad DX and bad UX.
- Comparison with React Native's KeyboardAvoidingView
 - Comparison with react-native-keyboard-aware-scroll-view
 
 - Written in pure TypeScript
 
This library requires react-native-reanimated
To install:
expo install react-native-reanimatedyarn add @good-react-native/keyboard-avoideryarn add @good-react-native/keyboard-avoider react-native-reanimated If you aren't using Expo, make sure to add the react-native-reanimated Babel Plugin to babel.config.js:
module.exports = {
    presets: [
      ...
    ],
    plugins: [
      ...
      'react-native-reanimated/plugin',
    ],
};Install cocoapods:
cd ios && pod installMake sure your Android keyboard avoiding behavior is set to adjustPan (this library assumes it is). If you're in a bare workflow, add this line to your android/app/src/main/AndroidManifest.xml:
<activity
    android:windowSoftInputMode="adjustPan"
>If you're using Expo, you will instead add this to app.json
  "expo": {
    "android": {
      "softwareKeyboardLayoutMode": "pan"
    }
  }First, you need to wrap your app in KeyboardAvoiderProvider:
export const App = () => (
  <KeyboardAvoiderProvider>
    <RestOfApp/>
  </KeyboardAvoiderProvider>
);This library has three primary components that make implementing keyboard avoiding behavior easy.
A view that simply gets out of the way of the keyboard regardless of what the rest of your screen and layout looks like:
export const MyScreen = () => (
  <View style={{flex: 1}}>
    <View style={{flex: 1}}/>
    <KeyboardAvoiderView>
        <TextInput>
    </KeyboardAvoiderView>
  </View>
);It wont break the rest of your layout, it's easy to understand, it just works.
A more responsive keyboard aware ScrollView that behaves predictably:
export const MyScreen = () => (
  <KeyboardAvoiderScrollView contentContainerStyle={{flexGrow: 1}}>
    <View style={{flex: 1}}/>
    <TextInput/>
  </KeyboardAvoiderScrollView>
);Optionally, you can create a section based scroll with the KeyboardAvoiderScrollSection component:
export const MyScreen = () => (
  <KeyboardAvoiderScrollView contentContainerStyle={{flexGrow: 1}}>
    <View style={{flex: 1}}/>
    <KeyboardAvoiderScrollSection>
        <TextInput/>
        <TextInput/>
    </KeyboardAvoiderScrollSection>
  </KeyboardAvoiderScrollView>
);This makes it where the entire section will by shown when any input within that section is focused:
A component that creates keyboard avoiding insets.
export const MyScreen = () => (
  <KeyboardAvoiderScrollView contentContainerStyle={{flexGrow: 1}}>
    <View style={{flex: 1}}/>
    <TextInput/>
  </KeyboardAvoiderScrollView>
);You can use this when you need some space to be created within a layout when the keyboard shows (like if you had a keyboard attached to the bottom of the screen):
The biggest issue with the React Native's KeyboardAvoidingView is that, as a developer, it's hard to reason about how the behaviors will end up functioning within a screen and doesn't work in all layouts (even when it should work probably work). For example, lets look at a very simple layout:
function DoesntWork() {
    return (
        <View style={{
            flex: 1,
        }}>
            <View
                style={{
                    height: Dimensions.get('window').height - 300,
                    width: '100%',
                    justifyContent: 'flex-start'
                }}
            />
            <KeyboardAvoidingView
              behavior='padding' // None of the three supported behaviors will work here. That's bad.
            >
                <TextInput
                    style={textInputStyle}
                />
                <TextInput
                    style={textInputStyle}
                />
            </KeyboardAvoidingView>
        </View>
    )
}KeyboardAvoidingView is not even able to avoid a keyboard in this very simple situation! None of its three behaviors will work here. That's crazy. This is a normal layout and it should be supported.
What if we just had a keyboard avoiding view that actually worked all the time, predictably? Well, now we do:
export function ReactNativeFixedExample() {
    return (
        <View style={{
            flex: 1,
        }}>
            <View
                style={{
                    height: Dimensions.get('window').height - 400,
                    width: '100%',
                    justifyContent: 'flex-start'
                }}
            >
                <Image
                    style={{
                        width: '100%',
                        height: '100%',
                        resizeMode: 'contain'
                    }}
                    source={require('../promo-image.png')}
                />
            </View>
            <KeyboardAvoiderView>
                <TextInput
                    style={textInputStyle}
                />
                <TextInput
                    style={textInputStyle}
                />
            </KeyboardAvoiderView>
        </View>
    )
}Our KeyboardAvoiderView will work in every situation, and it's never going to break your layout because it uses translations instead of animating properties that affect your layout such as height and padding. It's just a view that gets out of the way of the keyboard in a predictable way.
If you do need to alter the layout itself, then you can use our KeyboardAvoiderInsets for all such use cases.
Unlike <KeyboardAvoidingView/> behavior prop, <KeyboardAvoiderView/> avoidMode doesn't make you think about implementation details. Instead, it simply tells the <KeyboardAvoiderView/> where you would like it to move when the keyboard shows.
Part of the motivation for creating this library was to attempt to create a scroll view that fixed many of the issues found in react-native-keyboard-aware-scroll-view.
More responsive behavior. react-native-keyboard-aware-scroll-view doesn't scroll fast enough to avoid the keyboard:
And it can act janky in certain circumstances:
Our <KeyboardAvoiderScrollView/> does exactly what it should in all situations, it just gets the input out of the way with a smooth animation:
There is a noticeable UX improvement on Android as well.
Keyboard avoiding will look the same both within and outside of scroll views. Extra height is always applied consistently.
No "bounce glitch". Unfortunately, this is a glitch that has existed for years in react-native-keyboard-aware-scroll-view and it likely isn't going to be fixed any time soon: APSL/react-native-keyboard-aware-scroll-view#217
There is simply no way to reliably avoid the "bounce" if you're using @react-navigation (although you may be able to avoid it in some cases, it probably can't be solved for all).
React Native's KeyboardAvoidingView has been reported to have issues with this as well. Our library avoids any such issues by measuring the absolute position of elements on the screen.
This library allows for automatic scrolling to show entire views instead of only allowing scrolling to text inputs if the developer wants it. This feature can be used to create a better user experience if desired:
This library aims to provide consistent behavior between platforms by default, but having matching behavior is impossible in some cases because Android doesn't allow developers to disable system keyboard avoiding behavior without disabling keyboard events entirely.
One noteable default difference is that on iOS, <KeyboardAvoiderScrollView/> will attempt to stay still when the keyboard hides. This behavior can be disabled so that the cross platform behavior matches, via the prop iosHideBehavior='revert'.
If this library is missing some feature that you'd find valueable, please open an issue! We're hoping the community can help guide us in deciding which features to add next to this package and are very open to suggestions at the moment. And we would like to avoid adding any features that we aren't sure have value to developers.
For developer convenience, this repo is a React Native project. You can just pull it down and work within the project. Pull requests should only touch the src folder.
All of the components support the following props:
| Props | Type | Description | Default | 
|---|---|---|---|
| animationTime | number | Time to move the view out of the way when the keyboard opens. | 150 | 
| animationEasing | Animated.EasingFunction | Easing function to use for both opening and closing animation. Opening and closing animations will both use Easing.out(animationEasing). | 
Easing.quad | 
| extraSpace | number | How much space there should be between the keyboard avoiding element and the keyboard. | 20 | 
Supports all React Native View props as well as all common props.
Additionally, it supports the following props
| Props | Type | Description | Default | 
|---|---|---|---|
| avoidMode | 'whole-view' 'focused-input'  | 
Which avoid mode to use. 'whole-view' will move the entire view out of the way. 'focused-input' will move just enough to show the input plus the extra space.  | 
'whole-view' | 
| enableAndroid | boolean | Enable keyboard avoiding on Android. | true | 
Supports all React Native ScrollView props as well as all common props.
Additionally, it supports the following props
| Props | Type | Description | Default | 
|---|---|---|---|
| iosHideBehavior | 'stay' 'revert'  | 
Behavior when the keyboard hides on iOS. 'stay' makes it where the scroll view stays where it is when the keyboard closes. 'revert' makes it where the scroll view returns to its original position.  | 
'stay' | 
Supports all common props.







