Handling Keyboard Appearance in React Native Chat UI (iOS & Android)

Handling Keyboard Appearance in React Native Chat UI (iOS & Android)



When building a chat-style interface in React Native, one of the most common UX problems is the input box being covered by the on-screen keyboard. This issue affects both iOS and Android, but the underlying behavior and fixes differ slightly.

In this post, I’ll walk through how we solved this problem in a real chat screen implementation, covering:

  • Using KeyboardAvoidingView correctly
  • Adjusting input position dynamically
  • iOS vs Android behavior differences
  • Why Android does require an AndroidManifest.xml change

1. Wrapping the Screen with KeyboardAvoidingView

The foundation of the solution is React Native’s built-in KeyboardAvoidingView. The entire chat screen is wrapped inside it:


<KeyboardAvoidingView
  style={styles.root}
  behavior="padding"
  keyboardVerticalOffset={Platform.OS === 'ios' ? 90 : 80}
>
  {/* Chat UI */}
</KeyboardAvoidingView>

This ensures that when the keyboard appears, the layout automatically adjusts and pushes the content upward instead of letting the keyboard overlap it.

For chat UIs, behavior="padding" provides the most stable and predictable results across devices.


2. Why keyboardVerticalOffset Matters

Without a proper keyboardVerticalOffset, the input field may:

  • Move too far upward
  • Still be partially hidden
  • Overlap with navigation headers

In this implementation, the offset is adjusted per platform:


keyboardVerticalOffset={Platform.OS === 'ios' ? 90 : 80}

Guidelines:

  • iOS: Account for status bar, safe area, and navigation header
  • Android: Smaller offset usually works better

3. FlatList and Keyboard Interaction

Chat messages are rendered using FlatList. To improve usability when the keyboard is open:


<FlatList
  keyboardDismissMode="on-drag"
  contentContainerStyle={styles.messagesContent}
/>

This allows users to dismiss the keyboard naturally by scrolling the chat history, which feels intuitive and avoids gesture conflicts.

Additionally, the list automatically scrolls to the bottom when new messages arrive:


useEffect(() => {
  flatListRef.current?.scrollToEnd({ animated: true });
}, [messages]);

4. Closing the Keyboard After Sending a Message

After sending a message, the keyboard is dismissed programmatically:


if (inputRef.current) {
  inputRef.current.blur();
}

This prevents layout jumping and creates a smoother chat experience, especially on Android devices.


5. Android: Required AndroidManifest.xml Configuration

Unlike iOS, Android requires an explicit system-level configuration for KeyboardAvoidingView to work reliably.

Make sure your AndroidManifest.xml includes:


<activity
  android:name=".MainActivity"
  android:windowSoftInputMode="adjustResize">

Why this is required:

  • adjustResize tells Android to resize the app window when the keyboard appears
  • Without it, the keyboard overlays the UI instead of pushing it upward
  • KeyboardAvoidingView alone is not sufficient on Android

This setting is essential for consistent behavior across different Android devices and OEMs.


6. iOS Notes

  • KeyboardAvoidingView works out of the box
  • behavior="padding" is the most stable option
  • Be mindful of safe areas on modern iPhones

Conclusion

To ensure a reliable chat input experience when the keyboard appears:

  • Wrap the screen with KeyboardAvoidingView
  • Set a proper keyboardVerticalOffset
  • Configure FlatList keyboard behavior
  • Update AndroidManifest.xml with adjustResize

With these steps combined, the input field remains visible and responsive on both iOS and Android.

Happy coding 🚀

❤️ Support This Blog


If this post helped you, you can support my writing with a small donation. Thank you for reading.


Comments

Popular posts from this blog

fixed: embedded-redis: Unable to run on macOS Sonoma

Copying MDC Context Map in Web Clients: A Comprehensive Guide

Reset user password for your own Ghost blog