useKeyboardHeight

A React Native hook that tracks keyboard visibility, height, and animation duration with cross-platform support and screen rotation handling.

Installation

pnpm dlx bna-ui add useKeyboardHeight

Usage

import { useKeyboardHeight } from '@/hooks/useKeyboardHeight';
export function KeyboardAwareView({ children }) {
  const { keyboardHeight, isKeyboardVisible, keyboardAnimationDuration } =
    useKeyboardHeight();
 
  return (
    <View>
      <Text>Keyboard Height: {keyboardHeight}</Text>
      <Text>Keyboard Visible: {isKeyboardVisible ? 'Yes' : 'No'}</Text>
      <Text>Animation Duration: {keyboardAnimationDuration}ms</Text>
    </View>
  );
}

API Reference

useKeyboardHeight

Returns keyboard state information including height, visibility, and animation duration with cross-platform compatibility.

Parameters

This hook takes no parameters.

Returns

PropertyTypeDescription
keyboardHeightnumberCurrent keyboard height in pixels (0 when hidden)
isKeyboardVisiblebooleanWhether the keyboard is currently visible
keyboardAnimationDurationnumberDuration of keyboard animation in milliseconds

Platform Differences

The hook handles platform-specific keyboard events automatically:

iOS

  • Uses keyboardWillShow and keyboardWillHide events for smoother animations
  • Provides accurate animation duration from the system
  • Handles landscape mode keyboard height adjustments
  • Default animation duration: 250ms

Android

  • Uses keyboardDidShow and keyboardDidHide events
  • May not always provide animation duration (fallback: 200ms)
  • Less predictable keyboard heights in landscape mode
// The hook automatically selects the right events
const showEvent =
  Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
const hideEvent =
  Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';

Advanced Features

Screen Rotation Support

The hook automatically handles screen rotation and adjusts keyboard height accordingly:

// Automatic landscape keyboard height adjustment on iOS
if (screenWidth > screenHeight && Platform.OS === 'ios') {
  const estimatedLandscapeHeight = Math.min(
    previousHeightRef.current,
    screenHeight * 0.4
  );
  setKeyboardHeight(estimatedLandscapeHeight);
}

Edge Case Handling

  • Invalid Heights: Filters out invalid or zero keyboard heights
  • Previous Height Tracking: Maintains reference to last valid height for calculations
  • Dimension Changes: Responds to screen size changes and split-screen scenarios
  • Memory Cleanup: Properly removes all event listeners on unmount

Use Cases

This hook is perfect for:

  • Creating keyboard-aware input forms and chat interfaces
  • Adjusting scroll view content insets when keyboard appears
  • Animating UI elements in sync with keyboard transitions
  • Building responsive layouts that adapt to keyboard presence
  • Implementing custom keyboard avoidance behaviors

Best Practices

Performance Optimization

Use the hook at the appropriate component level to minimize re-renders:

// Good: Use in parent component that needs to adjust layout
function ChatScreen() {
  const { keyboardHeight, isKeyboardVisible } = useKeyboardHeight();
 
  return (
    <View style={{ flex: 1, paddingBottom: keyboardHeight }}>
      <MessageList />
      <ChatInput />
    </View>
  );
}
 
// Avoid: Using in multiple child components
function MessageItem() {
  const { keyboardHeight } = useKeyboardHeight(); // Unnecessary
  // ...
}

Safe Area Compatibility

Combine with safe area insets for proper spacing:

import { useSafeAreaInsets } from 'react-native-safe-area-context';
 
export function SafeKeyboardView({ children }) {
  const { keyboardHeight, isKeyboardVisible } = useKeyboardHeight();
  const insets = useSafeAreaInsets();
 
  const bottomPadding = isKeyboardVisible ? keyboardHeight : insets.bottom;
 
  return (
    <View
      style={{
        flex: 1,
        paddingTop: insets.top,
        paddingBottom: bottomPadding,
        paddingLeft: insets.left,
        paddingRight: insets.right,
      }}
    >
      {children}
    </View>
  );
}

Troubleshooting

Common Issues

Keyboard height is 0 on Android:

  • Ensure android:windowSoftInputMode="adjustResize" is set in your AndroidManifest.xml
  • Check that your app is not using android:windowSoftInputMode="adjustPan"

Inconsistent behavior in landscape mode:

  • The hook includes landscape detection and adjustment for iOS
  • Android landscape keyboard behavior varies by device and keyboard app

Animation timing doesn't match system keyboard:

  • iOS provides accurate animation duration from the system
  • Android may require manual duration tuning based on your app's needs

Debug Information

Add debug logging to understand keyboard behavior:

export function DebugKeyboardInfo() {
  const { keyboardHeight, isKeyboardVisible, keyboardAnimationDuration } =
    useKeyboardHeight();
 
  return (
    <View
      style={{
        position: 'absolute',
        top: 100,
        left: 20,
        backgroundColor: 'rgba(0,0,0,0.8)',
        padding: 10,
      }}
    >
      <Text style={{ color: 'white' }}>Height: {keyboardHeight}px</Text>
      <Text style={{ color: 'white' }}>
        Visible: {isKeyboardVisible ? 'Yes' : 'No'}
      </Text>
      <Text style={{ color: 'white' }}>
        Duration: {keyboardAnimationDuration}ms
      </Text>
      <Text style={{ color: 'white' }}>Platform: {Platform.OS}</Text>
    </View>
  );
}

Dependencies

  • react - Required for hooks functionality
  • react-native - Required for Keyboard API and platform detection

Accessibility

The hook supports accessibility by:

  • Preserving keyboard navigation patterns
  • Maintaining focus management during keyboard transitions
  • Supporting screen readers by keeping content visible above keyboard
  • Enabling proper scrolling behavior for assistive technologies

References

Learn more about keyboard handling in React Native: