96

KeyboardAvoidingView not Working Properly

I am trying to use the KeyboardAvoidingView with behavior="padding".

For some reason, when I'm trying to enter any text in TextInput, there's a space below the TextInput. Attached is a picture of what is happening as well as the code. Any chance anyone has any idea whats happening here?

Whats-App-Image-2018-01-24-at-5-07-46-PM

  render() {
    return (

      <KeyboardAvoidingView  style={{ flex: 1}}  behavior="padding">
      < View
          style={{
            flex: 1,
           
          backgroundColor: "#FFFFFF",
         
        }}
      >
        
        <ScrollView
          contentContainerStyle={{ justifyContent: "flex-end", flex: 1 }}>
                <ChatInfo />
              </ScrollView>

        
          <View style={styles.container}>
          <TextInput
            style={styles.input}
            underlineColorAndroid="transparent"
            autoCapitalize="none"
            onChangeText={text => this.setState({ text: text })}
            value={this.state.text}
          />

          <TouchableOpacity
            style={styles.submitButton}
            onPress={this.submitName}
          >
            <Text style={styles.submitButtonText}> SEND </Text>
          </TouchableOpacity>
        </View>
       
      </ View>
      </KeyboardAvoidingView>
    );
  }
}

export default connect()(ChatScreen);

const styles = StyleSheet.create({
  input: {
    margin: 2,
    paddingLeft: 15,
    flex: 1,
    height: 40,
    padding: 10,
    fontSize: 14,
    fontWeight: "400"
  },

      container: {
        borderTopWidth: 1,
        minWidth: "100%",
        borderColor: "#cccccc",
        height: 44,
        flexDirection: "row",
        justifyContent: "space-between",
        backgroundColor: "#fff"
        
      },

  submitButtonText: {
    color: "#0a9ffc",
    fontSize: 14,
    fontWeight: "500"
  },

  submitButton: {
    backgroundColor: "#fff",
    padding: 10,
    margin: 2,
    height: 40,
    alignItems: "center",
    justifyContent: "center"
  }
});
Community
  • 1
  • 1
Charan Teja
  • 959
  • 1
  • 7
  • 6
  • 1
    Try removing `paddingBottom: this.keyboardHeight` and add `flex: 1` to keyboardavoidingview styles. – HSBP Jan 24 '18 at 11:11
  • still not working@HSBP – Charan Teja Jan 24 '18 at 11:50
  • Use _KeyboardAwareScrollView_ (https://github.com/APSL/react-native-keyboard-aware-scroll-view) instead of _ScrollView_. Also you can try removing flex: 1 for TextInput style. – HSBP Jan 25 '18 at 07:44
  • 1
    @CharanTeja Did you able to solve the problem? Can you add code of . I have tried removing some of your code. Its working. – PK86 Feb 08 '18 at 13:38

26 Answers26

159

If you are using react-navigation, this is affected by the header of the react-navigation. The height of the header varies on different mobile screens. So you have to get the height of the header and pass it into the keyboardVerticalOffset props.

import * as React from 'react'
import { KeyboardAvoidingView } from 'react-native'
import { useHeaderHeight } from '@react-navigation/elements'

type Props = {
  children: React.ReactNode
}

export const KeyboardShift = ({ children }: Props) => {
  const height = useHeaderHeight()

  return (
    <KeyboardAvoidingView
      keyboardVerticalOffset={height + 47}
      behavior="padding"
      style={{ flex: 1 }}
      enabled>
      {children}
    </KeyboardAvoidingView>
  )
}
shim
  • 9,289
  • 12
  • 69
  • 108
Benson Toh
  • 1,970
  • 1
  • 10
  • 13
  • 7
    For me `keyboardVerticalOffset={Header.HEIGHT + 64}` was the sweet spot. Thanks! – Sloth Armstrong Jan 16 '19 at 17:05
  • 3
    Just for clarify: I was still having some issues where just the `TextInput` goes up with _keyboard_ (if I have a for example a `Button` or a `Text` it doesn't go up). To fix that, I wrapped the `TextInput` and the `Button` (or anything else) into a `View`. – Israel Nascimento Feb 03 '19 at 19:43
  • Just to add this is not working for iPhone x devices. Can you suggest for x devices also? – Akhil kumar Amarneni Sep 29 '19 at 14:13
  • 2
    It seems you need to access Header from a new package now import { Header } from "react-navigation-stack"; – Hylle Oct 16 '19 at 02:45
  • 9
    To build on @Hylle, for functional components use `import { useHeaderHeight } from 'react-navigation-stack'` and then `const headerHeight = useHeaderHeight()`. Additionally, instead of using an arbitrary number, just add the heights up like so: `const keyboardVerticalOffset = Constants.statusBarHeight + headerHeight`. If you're using an InputAccessoryView, add the height of it there as well. – Garrett Aug 27 '20 at 22:54
  • For those using Expo, you can get statusBarHeight from expo-constants `import Constants from 'expo-constants'` `console.log(Constants.statusBarHeight)` – Chen W Jan 19 '23 at 00:26
  • why 47?????????? – famfamfam Aug 10 '23 at 09:20
64

This is a known issue with KeyboardAvoidingView and Android. There are multiple ways to address this issue.

React Native documentation says:

Android may behave better when given no behavior prop at all, whereas iOS is the opposite.

So, if you are working only with Android you may remove behavior prop and it should work straight away. For best results add android:windowSoftInputMode="adjustResize" to your Manifest.

Alternatively you can give an offset value that works for you something like this: KeyboardAvoidingView keyboardVerticalOffset={-500} behavior="padding"

For iOS do the same thing conditionally:

behavior= {(Platform.OS === 'ios')? "padding" : null}

keyboardVerticalOffset={Platform.select({ios: 0, android: 500})}

shim
  • 9,289
  • 12
  • 69
  • 108
Pavan Mallela
  • 741
  • 4
  • 3
  • 19
    `Platform` now has a `select()` method, so you can do something like this as well: `behavior={Platform.select({android: undefined, ios: 'padding'})}` – rnevius Sep 10 '18 at 09:58
  • 4
    In my case, I was only able to get this working with `behavior` set to `padding` on both platforms. Setting it to `null` on Android didn't have any effect. – Gavin Dec 05 '18 at 11:23
  • @rnevius note you can leave out the `android: undefined`. – shim Aug 03 '23 at 03:09
30

WARNING

This appears to be only a partial solution, although it works initially, if the android phone is locked on the screen with the keyboard avoiding layout, when you unlock you end up with the extra padding above the keyboard again.

tl;dr

Remove android:windowSoftInputMode="adjustResize" from the AndroidManifest.xml

Before

...
<activity
  android:name=".MainActivity"
  android:label="@string/app_name"  
  android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
  android:windowSoftInputMode="adjustResize"
  >
...

After

...
<activity
  android:name=".MainActivity"
  android:label="@string/app_name"  
  android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
  >
...

Why

If I understand the issue correctly, I have been dealing with the same thing. By having android:windowSoftInputMode="adjustResize" in the manifest, the android system will try to do the same job as the KeyboardAvoidingView. This results in extra spacing being added above the keyboard on Android only.

If working on both platforms you are going to have to deal with this on iOS every time you are working with keyboard input, so best to remove the android specific behaviour by android:windowSoftInputMode="adjustResize" from the manifest and using the KeyboardAvoidingView every time.

Bulwinkel
  • 2,111
  • 25
  • 23
  • Were you still facing issues when you removed 'padding' from the behavior in the KeyboardAvoidingView? Is that why you resorted to removing android:windowSoftInputMode from the manifest? – johnny Jul 12 '18 at 23:32
  • I left the behaviour as padding, as the other options seemed to broken. – Bulwinkel Jul 13 '18 at 01:32
  • I want to set a fixed bottom button after the scrollView.But it's not woking well. – Johncy Jan 30 '19 at 06:37
  • Set android:windowSoftInputMode to adjustPan and it will work even after phone enters sleep mode – Bravo Apr 08 '21 at 20:25
22

For anyone coming here in 2021, a few things for an updated answer:

  • useHeaderHeight is no longer exported by @react-navigation/stack, it is in @react-navigation/elements.

  • React Native also now recommends setting the behavior prop for both iOS and Android. So the full solution would be:

import { useHeaderHeight } from '@react-navigation/elements';

export const MyComponent = () => {
  const headerHeight = useHeaderHeight();
  return (
      <KeyboardAvoidingView
        keyboardVerticalOffset={headerHeight}
        style={style.container}
        behavior={Platform.OS === "ios" ? "padding" : "height"}
      >
      {/* rest of your component */}
      </KeyboardAvoidingView>
    );
}

I didn't have to add any additional value to headerHeight in keyboardVerticalOffset, and it's working great on iOS and Android.

EDIT: The problem now goes deeper, as KeyboardAvoidingView does not support all types of Android keyboards. The solution must rely on opening the keyboard to a specific element then (for example a text input). This custom component would look like this:

import React, { PropsWithChildren, useEffect, useState } from 'react';
import { Platform, Animated, Dimensions, Keyboard, KeyboardAvoidingView, StyleSheet, TextInput } from 'react-native';
import {useHeaderHeight} from '@react-navigation/elements';
import { useKeyboard } from '@react-native-community/hooks';

export default function KeyboardShift (props: PropsWithChildren<{}>) {
  const [shift, setShift] = useState(new Animated.Value(0))
  const keyboard = useKeyboard()

  // On mount, add keyboard show and hide listeners
  // On unmount, remove them
  useEffect(() => {
    Keyboard.addListener('keyboardDidShow', handleKeyboardDidShow);
    Keyboard.addListener('keyboardDidHide', handleKeyboardDidHide);
    return () => {
      Keyboard.removeAllListeners('keyboardDidShow');
      Keyboard.removeAllListeners('keyboardDidHide');
    }
  }, [])

  const handleKeyboardDidShow = () => {
    const { height: windowHeight } = Dimensions.get('window');
    const keyboardHeight = keyboard.keyboardHeight;
    const currentlyFocusedInputRef = TextInput.State.currentlyFocusedInput();
    currentlyFocusedInputRef.measure((x, y, width, height, pageX, pageY) => {
      const fieldHeight = height;
      const fieldTop = pageY;
      const gap = (windowHeight - keyboardHeight) - (fieldTop + fieldHeight);
      if (gap >= 0) {
        return;
      }
      Animated.timing(
        shift,
        {
          toValue: gap,
          duration: 1000,
          useNativeDriver: true,
        }
      ).start();
    })
  }

  const handleKeyboardDidHide = () => {
    Animated.timing(
      shift,
      {
        toValue: 0,
        duration: 1000,
        useNativeDriver: true,
      }
    ).start();
  }

  const { children } = props;

  // Android: we need an animated view since the keyboard style can vary widely
  // And React Native's KeyboardAvoidingView isn't always reliable
  if (Platform.OS === 'android') {
    return (
      <Animated.View style={[styles.container, { transform: [{translateY: shift}] }]}>
        {children}
      </Animated.View>
    );
  }

  // iOS: React Native's KeyboardAvoidingView with header offset and 
  // behavior 'padding' works fine on all ios devices (and keyboard types)
  const headerHeight = useHeaderHeight();
  return (
    <KeyboardAvoidingView
      keyboardVerticalOffset={headerHeight}
      style={styles.container}
      behavior={'padding'}>
      {children}
    </KeyboardAvoidingView>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  }
});

Yes, it's unfortunately long-winded, but it gets the job done for all types of phones on both iOS and Android.

Read more about it here.

SECOND EDIT: As of April 22nd, 2022, I've replaced the complex solution above the following:

Step 1:

behavior={Platform.OS === "ios" ? "padding" : undefined}

Step 2:

Be sure to REMOVE

android:windowSoftInputMode="adjustPan"

(Or any windowSoftInputMode for that matter) from your AndroidManifest.xml file.

So far this solution has been working as well (and is way less code - always better, right?)

fullStackChris
  • 1,300
  • 1
  • 12
  • 24
17

The KeyboardAvoidingView must be a ScrollView child, not the other way around. This way it behaves normal(normal for what purpose I am using it). Try it and let me know how it went.

<ScrollView>
    <KeyboardAvoidingView styles={styles.container} behavior='padding'>

    </KeyboardAvoidingView>
</ScrollView>
RRikesh
  • 14,112
  • 5
  • 49
  • 70
12

I think this is because the behavior props value, so I think adding this line in the keyboardavoidview will help

<KeyboardAvoidingView
    style = {{ flex: 1 }}
    behavior={Platform.OS === "ios" ? "padding" : null}>
</KeyboardAvoidingView>
nilskp
  • 3,097
  • 1
  • 30
  • 34
7

The main issue with KeyboardAvoidingView is that; the understanding of how it works is missing.

I found below link very helpful

https://medium.com/@nickyang0501/keyboardavoidingview-not-working-properly-c413c0a200d4

  1. First thing, use of flex:1 in KeyboardAvoidingView and behavior: 'padding'
  2. Next is use of flex:1 in "MainView" which needs to go inside KeyboardAvoidingView
  3. Last is adding justifyContent: "flex-end" to ""MainView""

Hope it helps

Amit
  • 2,389
  • 22
  • 29
6

For React Native Navigation v5, you can use the following:

import { useHeaderHeight } from '@react-navigation/stack';

...

const Component = () => (

<KeyboardAvoidingView
  keyboardVerticalOffset={ useHeaderHeight() } // <-- for v5
  behavior="padding"
  style={{ flex: 1 }}
>
  <TextInput
    style={{ height: 30, width: "100%, borderWidth: 1 }}
  />
</KeyboardAvoidingView

)

https://reactnavigation.org/docs/stack-navigator#headertransparent

Scott
  • 1,207
  • 2
  • 15
  • 38
4

Many answers here have shown a conditional behavior prop value. Like this.

// incorrect 
<KeyboardAvoidingView
    style = {{ flex: 1 }}
    behavior={Platform.OS === "ios" ? "padding" : null}>
</KeyboardAvoidingView>

But this sets the behavior prop to null on Android.

The documentation says...

Android and iOS both interact with this prop differently.
Android may behave better when given no behavior prop at all, whereas iOS is the opposite.

Conditional spreading the behavior prop provides an exact solution.
It adds the prop on iOS and leaves it out on Android.

// correct 
<KeyboardAvoidingView
    style = {{ flex: 1 }}
    {...(Platform.OS === 'ios' && { behavior: 'padding' })}
</KeyboardAvoidingView>

And here's a solution if using styled-components that doesn't use an unnecessary KeyboardAvoidingView on Android.

import { KeyboardAvoidingView as Kav, Platform, View } from 'react-native';
import styled from 'styled-components/native';

// If ios we change the component type and, via the `attrs` method, add a behavior prop. This
// approach leaves Android alone. Because it already works.
export const ScreenContainer = styled(Platform.OS === 'ios' ? Kav : View).attrs({
  behavior: Platform.OS === 'ios' && 'padding',
})`
  flex: 1;
`;
GollyJer
  • 23,857
  • 16
  • 106
  • 174
  • Setting the behavior to undefined is the same as "no prop at all". behavior={Platform.OS === "ios" ? "padding" : undefined} – Zoltán Hajdú Sep 14 '21 at 08:48
3

A handy alternative when wanting to avoid the keyboard with a ScrollView is the popular react-native-keyboard-aware-scroll-view package:

https://github.com/APSL/react-native-keyboard-aware-scroll-view

import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'

<KeyboardAwareScrollView>
  <View>
    <TextInput />
  </View>
</KeyboardAwareScrollView>
fredrivett
  • 5,419
  • 3
  • 35
  • 48
2

UPDATE: 2021(October)

If you are using react-navigation(currently, I'm using v6), import useHeaderHeight hook(require additional dependencies)

If you want to use ScrollView with KeyboardAvoidingView, you have to wrap ScrollView inside KeyboardAvoidingView(see example below)

NOTE: If your screen have bottomTabsNavigation, be sure to DISABLE on iOS platform tabBarHideOnKeyboard: Platform.OS !== 'ios'

   const headerHeight = useHeaderHeight();
    
      <KeyboardAvoidingView 
        behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
        style={{flex: 1}}
        keyboardVerticalOffset={headerHeight}>
         <ScrollView style={{flex: 1}} contentContainerStyle={{flexWrap: 1}}>
             ...content
         </ScrollView>
    
      </KeyboardAvoidingView/>
1
<KeyboardAvoidingView styles={styles.container} behavior = 'padding'  enabled>
   <ScrollView>

        <View>
          ....
        </View>

   </ScrollView>
</KeyboardAvoidingView>
YassR
  • 19
  • 1
  • 17
    Welcome to StackOverflow YassR. When posting an answer, try to also explain what your answer does and how it answers the question. For more information, see ["How do I write a good answer?"](https://meta.stackoverflow.com/help/how-to-answer) in the [Help Center](https://meta.stackoverflow.com/help). – GGG Aug 26 '18 at 20:02
  • 1
    This answer is given in previous answers. Also, enabled is true by default - why do you need to add it? – Chanoch Mar 21 '19 at 12:25
1

My issue was with the keyboardHidesTabBar option. The following setup worked for me:

const AppBottomTabNavigator = createBottomTabNavigator(
  {
    ...
  },
  {
    tabBarOptions: {
      keyboardHidesTabBar: Platform.OS !== 'ios',
    },
  },
);

Component:

import React from 'react';
import {
  Keyboard,
  KeyboardAvoidingView,
  Platform,
  StyleSheet,
  Text,
  TextInput,
  TouchableWithoutFeedback,
  View,
} from 'react-native';
import { Header } from 'react-navigation-stack';

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  center: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  textInput: {
    height: 40,
    borderColor: 'gray',
    borderWidth: 1,
  },
});

const MyScreen = () => {
  return (
    <KeyboardAvoidingView
      behavior={Platform.OS === 'ios' ? 'padding' : null}
      keyboardVerticalOffset={Header.HEIGHT}
      style={styles.container}
    >
      <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
        <View style={styles.container}>
          <View style={[styles.container, styles.center]}>
            <Text>Hello!</Text>
          </View>
          <TextInput style={styles.textInput} placeholder="Message" />
        </View>
      </TouchableWithoutFeedback>
    </KeyboardAvoidingView>
  );
};

export default MyScreen;
Daniel Tovesson
  • 2,550
  • 1
  • 30
  • 41
1
<KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : null} 
style={{flex: 1 }}>

In the above snippet, flex is set to 1, which renders the text Input field just above the keyboard by default even when the keyboard isn't opened. And, when the keyboard pops up, the input field is further pushed up by a factor of keyboard height's offset.

Setting flex to 0 shall fix the issue, as it did in my case.

 <KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : null} 
  style={{flex: 0 }}>
  <View>
   ...
  </View>
 </KeyboardAvoidingView>
Prajwal Kulkarni
  • 1,480
  • 13
  • 22
1

I think the best approach is to create a HOC for this, in addition ,by using getBottomSpace from react-native-iphone-x-helper you can solve overlapping issue for IPhone X and..

 import React, { ComponentType, ReactNode } from 'react';
    import { Platform, KeyboardAvoidingView, View, Pressable, Keyboard } from 
    'react-native';
    import { getBottomSpace } from 'react-native-iphone-x-helper';

    interface IProps {
    children: ReactNode;
    }

    const KeyboardAvoidingViewHoc = (Component: ComponentType) => {
    return ({ children, ...props }: IProps) => {
    return (
      <KeyboardAvoidingView  {...props} keyboardVerticalOffset= 
   {getBottomSpace()} behavior= {Platform.OS === 'ios' ? 'padding' : undefined}>
        <Pressable onPress={Keyboard.dismiss}>
          <Component {...props}>{children}</Component>
        </Pressable>
      </KeyboardAvoidingView>
    );
  };
};

export const AvoidKeyboardAvoidingViewHoc = KeyboardAvoidingViewHoc(View);
Vahid
  • 1,258
  • 1
  • 14
  • 14
1

After applying ScrollView the problem was solved for me.

double-beep
  • 5,031
  • 17
  • 33
  • 41
Sooma
  • 11
  • 1
1

What worked for me in 2022

The problem I was having (on Android devices only) was that when I tapped on an input text field, the keyboard would show. Upon dismissing the keyboard, either by tapping the tick icon on it or tapping anywhere outside the keyboard, the <KeyboardAvoidingView /> component (part of React Native) would not resize properly, so the screen was half the height (device height minus keyboard height).

Various approaches worked but quite poorly, until I took this approach. Below, is a code snippet of how I put this together.

import React, { useEffect } from 'react';
import {
  KeyboardAvoidingView,
  NativeModules,
  Platform,
  TextInput,
} from 'react-native';

const isIos: boolean = Platform.OS === 'ios';
const isAndroid: boolean = Platform.OS === 'android';

export const MyComponent = (): JSX.Element => {

  useEffect((): (() => void) => {
    if (isAndroid) {
      NativeModules.AndroidUtils.setWindowAdjustResize()
    }

    return (): void => {
      if (isAndroid) {
        NativeModules.AndroidUtils.setWindowAdjustPan()
      }
    }
  }, [])


  return (
    <KeyboardAvoidingView
      behavior={isIos ? 'padding' : undefined}
      style={{ flex: 1 }}
    >
      <ScrollView>
        <View style={{ paddingTop: 300 }}>
          <TextInput />
        </View>
      </ScrollView>
    </KeyboardAvoidingView>
  );
}

Other info

  • using React Native 0.68.3 with Wix React Native Navigation
  • android:windowSoftInputMode="adjustPan" has NOT been removed from .MainActivity inside the AndroidManifest.xml file.
matfin
  • 499
  • 4
  • 15
1

It took me awhile to find an answer that both worked and made sense to me. Now that I have one, I'll share here.

To my future self and anyone else having issues with this:

From the KeyboardAvoidingView docs on keyboardVerticalOffset

This is the distance between the top of the user screen and the react native view, may be non-zero in some use cases.

Depending on what is in your app view, you need to add up the distance between top of user screen and react native view. This was surprising to me since I expected it to be the bottom.

Most commonly this will be

// if you're using react navigation
import { useHeaderHeight } from '@react-navigation/elements';
const headerHeight = useHeaderHeight();

// if you're using safe area views
import { useSafeAreaInsets } from 'react-native-safe-area-context'
const insets = useSafeAreaInsets()

<KeyboardAvoidingView
  behavior='padding'
  keyboardVerticalOffset={insets.top + headerHeight}
>
</KeyboardAvoidingView>

Alex Choi
  • 191
  • 2
  • 13
1

the KeyboardAvoidingView use , i found it has a important principle.

that is KeyboardAvoidingView must in Highest level dom.


is is no working

<Fragment>
  <View style={tw`relative bg-gray-100 h-full`}>
    <SafeAreaView style={tw`bg-gray-100`} />

    <FlatList
      style={tw`px-4`}
      data={messages}
      renderItem={({ item }) => <MessageItem message={item} />}
      keyExtractor={item => item.id}></FlatList>
      
    <KeyboardAvoidingView style={tw`bg-gray-200`}>
      <InputFooter />
    </KeyboardAvoidingView>
  </View>
</Fragment>

this is working

<KeyboardAvoidingView
  behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
  keyboardVerticalOffset={16}
  style={tw`bg-gray-200`}
>
  <View style={tw`relative bg-gray-100 h-full`}>
    <SafeAreaView style={tw`bg-gray-100`} />

    <FlatList
      style={tw`px-4`}
      data={messages}
      renderItem={({ item }) => <MessageItem message={item} />}
      keyExtractor={item => item.id}></FlatList>

    <SafeAreaView style={tw`bg-gray-200`}>
      <InputFooter />
    </SafeAreaView>
  </View>
</KeyboardAvoidingView>
peterZhang
  • 11
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 16 '23 at 05:13
0

My problem was not checking this platform type

adding the code below to KeyboardAvoidView fixed it for me

behavior={Platform.OS === "ios" ? "padding" : 'height'}
delavago1999
  • 246
  • 2
  • 11
0

I had a similar issue because I'm using @react-navigation with bottom tabs.

Starting with "@react-navigation/bottom-tabs": "^5.11.2" you can get the height of the bottom tab bar with one of the following two ways (API reference):

import { BottomTabBarHeightContext } from '@react-navigation/bottom-tabs';

// ...

<BottomTabBarHeightContext.Consumer>
 {tabBarHeight => (
   /* render something */
 )}
</BottomTabBarHeightContext.Consumer>

or

import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';

// ...

const tabBarHeight = useBottomTabBarHeight();

and then you set it as offset to your KeyboardAvoidingView:

<KeyboardAvoidingView keyboardVerticalOffset={tabBarHeight} behavior={Platform.OS === "ios" ? "padding" : null} style={styles.container}>
  // ...
</KeyboardAvoidingView>
Georgios
  • 4,764
  • 35
  • 48
0

Keep in mind is always your top Parent with flex:1 then the child is then you text input container if you use this method it work always its test method.

<KeyboardAvoidingView style={{  flex: 1 }}
    behavior={Platform.OS === "ios" ? "position" : null} enabled>
      <ScrollView>
        <View>
          <View >
            <Text maxFontSizeMultiplier={1.5} >
              Sign in to your account{" "}
            </Text>
             <View
                behavior="padding"
                enabled
              >
                <TextInput
                  placeholder="Email address"
                  placeholderTextColor={Colors.grey}
                  style={styles.textInput}
                  onChangeText={(e) => setEmail(e.trim())}
                  autoCapitalize="none"
                  returnKeyType={"done"}
                />
              </View>
        </View>
      </ScrollView>
</KeyboardAvoidingView>
0

import { HeaderHeightContext } from "react-navigation-stack"; import { ..., KeyboardAvoidingView, } from "react-native";

<HeaderHeightContext.Consumer>
  {(headerHeight) => (
    <KeyboardAvoidingView
      {...(Platform.OS === "ios" && { 
            behavior: "padding",
            keyboardVerticalOffset: headerHeight
      })}
       style={{ flex: 1 }}>

 code is here 

</KeyboardAvoidingView>

)} </HeaderHeightContext.Consumer> enter image description here

enter image description here

0

I went through most of these comments and there are 2 major real life scenarios here:

  1. Chat - the keyboard must avoid the message input and push the conversation content above.

import { useHeaderHeight } from "@react-navigation/elements"
import {
  Keyboard,
  Platform,
  TouchableWithoutFeedback,
  View,
  KeyboardAvoidingView
} from "react-native"

const Chat = () => {
    // This is the crucial variable we will place it in
    // KeyboardAvoidingView -> keyboardVerticalOffset
    const headerHeight = useHeaderHeight()
    
    return (
      <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
        <KeyboardAvoidingView
          style={{ position: "absolute", bottom: 0, left: 0, right: 0 }}
          behavior={Platform.OS === "ios" ? "padding" : "height"}
          // If you want the input not to stick exactly to the keyboard
          // add a const here for example headerHeight + 20
          keyboardVerticalOffset={headerHeight}
        >
          <ScrollView style={{ flex: 1 }}>
             // Messages here
          <ScrollView />
          <View style={{ flex: 1, justifyContent: "flex-end" }}>
            <InputWrapper>
              <RawInput />
            </InputWrapper>
          </View>
        </KeyboardAvoidingView>
     </TouchableWithoutFeedback>
   )
}
  1. Form - https://medium.com/@nickyang0501/keyboardavoidingview-not-working-properly-c413c0a200d4 this article is a really good example how to handle it with the form. In order to make it even better use the approach I used for chat.
const headerHeight = useHeaderHeight()

<KeyboardAvoidingView
   style={{ position: "absolute", bottom: 0, left: 0, right: 0 }}
   behavior={Platform.OS === "ios" ? "padding" : "height"}
   keyboardVerticalOffset={headerHeight}
 >
  ....
</KeyboardAvoidingView>
0

Just change behavior from padding to heigh , this has fixed my problem

      <KeyboardAvoidingView 
  behavior='heigh'
  style={styles.container}>
    <View style={styles.bannerContainer}>
    <BannerEtudiant BannerText="Le coin des juristes" BannerImage={pictures.Banners.EtudiantBanner} />
  </View>
  <ScrollView style={styles.formContainer}  >

    <View style={styles.fieldContainer}>
      <Text style={styles.label}>Ancien Mot de passe</Text>
      <TextInput secureTextEntry={true} style={styles.textInput} onChangeText={setoldPassword}  />
      <Image source={pictures.Vector.VectorAnonyme} style={{position:'absolute',tintColor:'gray',width:20,height:20,top:40,right:5}} />
    </View>
    <View style={styles.fieldContainer}>
      <Text style={styles.label}>Nouveau Mot de passe</Text>
      <TextInput secureTextEntry={true} style={styles.textInput} onChangeText={setnewPassword}  />
      <Image source={pictures.Vector.VectorAnonyme} style={{position:'absolute',tintColor:'gray',width:20,height:20,top:40,right:5}} />
    </View>
    <View style={styles.fieldContainer}>
      <Text style={styles.label}>Confirmer le nouveau Mot de passe</Text>
      <TextInput secureTextEntry={true} style={styles.textInput} onChangeText={setconfnewPassword} />
      <Image source={pictures.Vector.VectorAnonyme} style={{position:'absolute',tintColor:'gray',width:20,height:20,top:40,right:5}} />
    </View>

    <TouchableOpacity style={styles.confirmButton} onPress={handleConfirm}>
      <Text style={styles.confirmButtonText}>Confirmer</Text>
    </TouchableOpacity>
          
  </ScrollView>
</KeyboardAvoidingView>

This worked for me

Ali Soussi
  • 1
  • 1
  • 1
-1
 <KeyboardAvoidingView style={styles.keyboardcontainer} behavior="padding"
       keyboardVerticalOffset={Platform.select({ios :120, android : 500})}
       enabled>

    <View  style={{flex: 1 }}>
        // Your Code 
    </View>

</KeyboardAvoidingView>
Keshav Gera
  • 10,807
  • 1
  • 75
  • 53