'KeyboardAvoidingViev not working on iOS with react navigation header and material bottom tabs?

You find a minimal repo here and a minimal snack available here. They both show the issue nicely with very minimal code.

I found lots of questions online about how to use KeyboardAvoidingViev with react navigation e.g. The popular proposed solution is

keyboardVerticalOffset={headerHeight + 64}

That does not work completely for me. The 64 seems arbitrary and somehow on iOS the view shrinks after closing the keyboard. Issue on iOS

Here is what I know so far:

  • It is definitely react navigation (headers and/or Material Bottom Tabs Navigator) and KeyboardAvoidingViev working together. If you remove the Material Bottom Tabs Navigator, it works.
  • Solutions including SafeAreaView did make it worse
  • Solutions with behavior={"position"} did make it worse
  • Solutions with +64 are not working
  • I found out that the solution of David Scholz works nicely, if I remove the Material Bottom Tabs Navigator.
  • Everything works fine on android (Samsung Galaxy 7S and emulator). From what I know, I would recommend to avoid KeyboardAvoidingViev with react navigation on android. So in fact, KeyboardAvoidingViev is also not working fully for android, but you don't need to use it.

Any help is appreciated. Thank you!



Solution 1:[1]

There is no need to add 64 to the headerHeight. Here is how I would solve this problem.

const flatListRef = createRef()
const [data, setData] = useState()
const headerHeight = useHeaderHeight();

<View style={{ flex: 1 }}>
        <KeyboardAvoidingView
          behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
          keyboardVerticalOffset={headerHeight}
          style={{ flex: 1 }}>
          <FlatList
            data={data}
            ref={flatListRef}
            onContentSizeChange={() =>
              flatListRef.current.scrollToEnd({ animated: true })
            }
            onLayout={() => flatListRef.current.scrollToEnd({ animated: true })}
            keyExtractor={(item) => item.id}
            renderItem={({ item }) => (
              <Text style={{ flex: 1, paddingVertical: 20 }}>{item.id}</Text>
            )}
          />
          <View style={{ flex: 1, marginBottom: 40 }}>
            <TextInput
              style={{
                backgroundColor: '#2E2E2E',
                width: '100%',
                borderRadius: 18,
                height: 36,
                paddingLeft: 10,
                paddingRight: 10,
                color: '#FFFFFF',
              }}
            />
          </View>
        </KeyboardAvoidingView>
      </View>

Here is a quick and dirty snack which contains an header from a StackNavigator.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David Scholz