All writing
React Native

Prevent the Keyboard from Covering React Native UI Components

Learn how to handle keyboard behavior gracefully in React Native apps

Prevent the Keyboard from Covering React Native UI Components

iOS doesn’t manage interactions between your app’s views and the keyboard by default. So the keyboard ends up covering input fields, users can’t dismiss it easily, and the UI doesn’t shift to compensate.

Here’s how I handle it.

The Solution

Two components do most of the work:

  1. KeyboardAvoidingView
  2. FlatList with keyboardDismissMode

A chat screen example:

import React from "react";
import {
  View,
  KeyboardAvoidingView,
  FlatList,
  TextInput,
  Platform,
  StyleSheet,
} from "react-native";

function ChatScreen() {
  // Sample messages data
  const messages = generateMessages(); // Your message generation logic

  return (
    <KeyboardAvoidingView
      behavior={Platform.OS === "ios" ? "padding" : "height"}
      style={styles.container}
    >
      <View style={styles.inner}>
        {/* Header/App Bar */}
        <View style={styles.header}>
          <Text>Chat</Text>
        </View>

        {/* Messages List */}
        <FlatList
          data={messages}
          keyboardDismissMode="interactive" // This is key!
          renderItem={({ item }) => (
            <MessageBubble text={item.text} isUser={item.source === "me"} />
          )}
          contentContainerStyle={styles.messageList}
        />

        {/* Input Area */}
        <View style={styles.inputContainer}>
          <TextInput
            style={styles.input}
            placeholder="Type a message..."
            multiline
          />
        </View>
      </View>
    </KeyboardAvoidingView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  inner: {
    flex: 1,
    backgroundColor: "#fff",
  },
  header: {
    height: 60,
    padding: 15,
    justifyContent: "center",
    borderBottomWidth: 1,
    borderBottomColor: "#eee",
  },
  messageList: {
    padding: 15,
  },
  inputContainer: {
    padding: 10,
    borderTopWidth: 1,
    borderTopColor: "#eee",
  },
  input: {
    borderRadius: 20,
    backgroundColor: "#f0f0f0",
    padding: 10,
    maxHeight: 100,
  },
});

Key Components

1. KeyboardAvoidingView

Wraps your screen and adjusts when the keyboard appears:

<KeyboardAvoidingView
  behavior={Platform.OS === "ios" ? "padding" : "height"}
  style={styles.container}
>
  {/* Your content */}
</KeyboardAvoidingView>

Props:

2. FlatList with Keyboard Dismiss

The keyboardDismissMode prop:

<FlatList
  keyboardDismissMode="interactive"
  // ... other props
/>

Options:

Handling Different Platforms

Android and iOS need different behaviors:

const keyboardBehavior = Platform.select({
  ios: "padding",
  android: "height",
});

function ChatScreen() {
  return (
    <KeyboardAvoidingView behavior={keyboardBehavior} style={styles.container}>
      {/* Content */}
    </KeyboardAvoidingView>
  );
}

Best Practices

  1. Test on both platforms
// Use Platform.select for platform-specific behavior
const styles = StyleSheet.create({
  input: {
    ...Platform.select({
      ios: {
        padding: 15,
      },
      android: {
        padding: 10,
      },
    }),
  },
});
  1. Handle keyboard events when needed
import { Keyboard } from "react-native";

// Listen for keyboard events if needed
React.useEffect(() => {
  const showSubscription = Keyboard.addListener("keyboardDidShow", (event) => {
    // Handle keyboard show
  });
  const hideSubscription = Keyboard.addListener("keyboardDidHide", (event) => {
    // Handle keyboard hide
  });

  return () => {
    showSubscription.remove();
    hideSubscription.remove();
  };
}, []);
  1. Adjust ScrollView/FlatList content
<FlatList
  keyboardDismissMode="interactive"
  keyboardShouldPersistTaps="handled"
  automaticallyAdjustKeyboardInsets={true}
  // ... other props
/>

Common Issues and Solutions

1. Keyboard Covering Input on iOS

// Add extra padding at bottom of ScrollView/FlatList
<FlatList
  contentContainerStyle={{
    paddingBottom: Platform.OS === "ios" ? 100 : 20,
  }}
/>

2. Input Not Visible When Keyboard Shows

// Scroll to input when keyboard shows
const inputRef = React.useRef(null);

React.useEffect(() => {
  const showSubscription = Keyboard.addListener("keyboardDidShow", () => {
    inputRef.current?.measureInWindow((x, y, width, height) => {
      // Scroll if needed
    });
  });

  return () => showSubscription.remove();
}, []);

Testing

Run through this list:

  1. Tap input, keyboard opens
  2. Input stays visible
  3. Scrolling with the keyboard open works
  4. Keyboard dismissal works
  5. Portrait and landscape
  6. A few iOS device sizes
0 claps
If this was useful, let me know.
What's New in React Native 0.76 Complete Guide to React Native Internationalization (i18n)