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:
KeyboardAvoidingViewFlatListwithkeyboardDismissMode
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:
behavior:'padding': adds padding (use on iOS)'height': adjusts height'position': changes position
keyboardVerticalOffset: extra offset if needed
2. FlatList with Keyboard Dismiss
The keyboardDismissMode prop:
<FlatList
keyboardDismissMode="interactive"
// ... other props
/>
Options:
'interactive': dismisses as you scroll (what you usually want)'on-drag': dismisses as soon as a scroll starts'none': default, never dismisses
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
- Test on both platforms
// Use Platform.select for platform-specific behavior
const styles = StyleSheet.create({
input: {
...Platform.select({
ios: {
padding: 15,
},
android: {
padding: 10,
},
}),
},
});
- 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();
};
}, []);
- 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:
- Tap input, keyboard opens
- Input stays visible
- Scrolling with the keyboard open works
- Keyboard dismissal works
- Portrait and landscape
- A few iOS device sizes
0 claps
If this was useful, let me know.