React Native UI Keyboard iOS

Prevent the Keyboard from Covering React Native UI Components

Learn how to handle keyboard behavior gracefully in React Native apps

5 min read

Prevent the Keyboard from Covering React Native UI Components

Hey there! 👋 Have you ever built a beautiful React Native app only to find the keyboard messing up your UI on iOS? You’re not alone! Today, I’ll show you how to handle keyboard behavior gracefully in your React Native applications.

The Problem

On iOS, there’s no default behavior for managing interactions between your app’s view and system UI elements like the keyboard. This can lead to frustrating user experiences where:

  • The keyboard covers your input fields
  • Users can’t dismiss the keyboard easily
  • The UI doesn’t adjust properly when the keyboard appears

Let’s fix these issues with a practical example using a chat application!

The Solution

We’ll look at two key components that solve these issues:

  1. KeyboardAvoidingView
  2. FlatList with keyboard dismiss mode

Here’s a complete 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 Explained

1. KeyboardAvoidingView

This is the wrapper component that manages keyboard interactions:

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

Important props:

  • behavior: Determines how the view adjusts:
    • 'padding': Adds padding to avoid the keyboard (recommended for iOS)
    • 'height': Adjusts height
    • 'position': Changes position
  • keyboardVerticalOffset: Additional offset if needed

2. FlatList with Keyboard Dismiss

The keyboardDismissMode prop is crucial for user experience:

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

Options for keyboardDismissMode:

  • 'interactive': Dismisses keyboard when scrolling (recommended)
  • 'on-drag': Dismisses immediately when scrolling starts
  • 'none': Doesn’t dismiss (default)

Handling Different Platforms

Remember that Android and iOS behave differently:

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

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

Best Practices

  1. Always 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
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 Your Implementation

Here’s a checklist for testing keyboard behavior:

  1. ✅ Open keyboard by tapping input
  2. ✅ Check if input is visible
  3. ✅ Try scrolling while keyboard is open
  4. ✅ Verify keyboard dismissal works
  5. ✅ Test in both portrait and landscape
  6. ✅ Test on different iOS devices

Conclusion

Handling keyboard behavior properly is crucial for a good user experience in React Native apps. By using KeyboardAvoidingView and proper FlatList configuration, you can create a smooth, native-feeling experience for your users.

Key takeaways:

  • Use KeyboardAvoidingView with proper behavior
  • Configure keyboardDismissMode on scrollable components
  • Test thoroughly on both platforms
  • Consider platform-specific adjustments

Have you encountered other keyboard-related challenges in React Native? Share your experiences in the comments below! 👇

Happy coding! 🚀