Skip to main content
The Keyboard module allows you to listen for native keyboard events and control the keyboard’s behavior, such as dismissing it programmatically.

Import

import { Keyboard } from 'react-native';

Methods

addListener()

Connects a JavaScript function to a keyboard event.
const subscription = Keyboard.addListener(eventType, listener);
eventType
KeyboardEventName
required
The keyboard event to listen for:
  • 'keyboardWillShow': Keyboard will appear (iOS only)
  • 'keyboardDidShow': Keyboard has appeared
  • 'keyboardWillHide': Keyboard will hide (iOS only)
  • 'keyboardDidHide': Keyboard has hidden
  • 'keyboardWillChangeFrame': Keyboard frame will change (iOS only)
  • 'keyboardDidChangeFrame': Keyboard frame changed (iOS only)
listener
function
required
Callback function invoked when the event fires. Receives a KeyboardEvent object.
Returns: EventSubscription - Object with a remove() method to unsubscribe.

dismiss()

Dismisses the active keyboard and removes focus from any focused input.
Keyboard.dismiss();

removeAllListeners()

Removes all listeners for a specific event type.
Keyboard.removeAllListeners(eventType);
eventType
KeyboardEventName
The event type to remove listeners for. If not provided, removes all listeners.

isVisible()

Returns whether the keyboard is currently visible.
const visible = Keyboard.isVisible();
Returns: boolean

metrics()

Returns the current keyboard metrics if the keyboard is visible.
const metrics = Keyboard.metrics();
Returns: KeyboardMetrics | null - Object with screenX, screenY, width, and height, or null if keyboard is hidden.

scheduleLayoutAnimation()

Synchronizes layout animations with keyboard movements.
Keyboard.scheduleLayoutAnimation(event);
event
KeyboardEvent
required
The keyboard event object received from a listener.

Types

KeyboardEvent

type KeyboardEvent = {
  duration: number;          // Animation duration in ms
  easing: KeyboardEventEasing;
  endCoordinates: KeyboardMetrics;
  startCoordinates?: KeyboardMetrics; // iOS only
  isEventFromThisApp?: boolean;       // iOS only
};

KeyboardMetrics

type KeyboardMetrics = {
  screenX: number;  // X position on screen
  screenY: number;  // Y position on screen
  width: number;    // Keyboard width
  height: number;   // Keyboard height
};

KeyboardEventEasing

type KeyboardEventEasing =
  | 'easeIn'
  | 'easeInEaseOut'
  | 'easeOut'
  | 'linear'
  | 'keyboard';

Examples

Basic Keyboard Dismissal

import React from 'react';
import {
  View,
  TextInput,
  Button,
  Keyboard,
  StyleSheet,
} from 'react-native';

const KeyboardDismissExample = () => {
  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        placeholder="Type here..."
      />
      <Button
        title="Dismiss Keyboard"
        onPress={() => Keyboard.dismiss()}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  input: {
    height: 40,
    borderWidth: 1,
    padding: 10,
    marginBottom: 20,
  },
});

Listening to Keyboard Events

import React, { useEffect, useState } from 'react';
import { View, Text, Keyboard } from 'react-native';

const KeyboardListener = () => {
  const [keyboardStatus, setKeyboardStatus] = useState('hidden');
  const [keyboardHeight, setKeyboardHeight] = useState(0);

  useEffect(() => {
    const showSubscription = Keyboard.addListener('keyboardDidShow', (e) => {
      setKeyboardStatus('shown');
      setKeyboardHeight(e.endCoordinates.height);
    });

    const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
      setKeyboardStatus('hidden');
      setKeyboardHeight(0);
    });

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

  return (
    <View>
      <Text>Keyboard Status: {keyboardStatus}</Text>
      <Text>Keyboard Height: {keyboardHeight}</Text>
    </View>
  );
};

Animated Content Shift

import React, { useEffect, useRef } from 'react';
import {
  View,
  TextInput,
  Animated,
  Keyboard,
  StyleSheet,
} from 'react-native';

const AnimatedKeyboardExample = () => {
  const offsetY = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    const keyboardWillShow = Keyboard.addListener(
      'keyboardWillShow',
      (e) => {
        Animated.timing(offsetY, {
          toValue: -e.endCoordinates.height / 2,
          duration: e.duration,
          useNativeDriver: true,
        }).start();
      },
    );

    const keyboardWillHide = Keyboard.addListener(
      'keyboardWillHide',
      (e) => {
        Animated.timing(offsetY, {
          toValue: 0,
          duration: e.duration,
          useNativeDriver: true,
        }).start();
      },
    );

    return () => {
      keyboardWillShow.remove();
      keyboardWillHide.remove();
    };
  }, [offsetY]);

  return (
    <Animated.View
      style={[
        styles.container,
        { transform: [{ translateY: offsetY }] },
      ]}
    >
      <TextInput
        style={styles.input}
        placeholder="Type here..."
      />
    </Animated.View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    padding: 20,
  },
  input: {
    height: 40,
    borderWidth: 1,
    padding: 10,
  },
});

Using scheduleLayoutAnimation

import React, { useEffect } from 'react';
import {
  View,
  TextInput,
  Keyboard,
  LayoutAnimation,
  StyleSheet,
} from 'react-native';

const LayoutAnimationExample = () => {
  useEffect(() => {
    const keyboardWillShow = Keyboard.addListener(
      'keyboardWillShow',
      (e) => {
        Keyboard.scheduleLayoutAnimation(e);
      },
    );

    const keyboardWillHide = Keyboard.addListener(
      'keyboardWillHide',
      (e) => {
        Keyboard.scheduleLayoutAnimation(e);
      },
    );

    return () => {
      keyboardWillShow.remove();
      keyboardWillHide.remove();
    };
  }, []);

  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        placeholder="Type here..."
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'flex-end',
    padding: 20,
  },
  input: {
    height: 40,
    borderWidth: 1,
    padding: 10,
  },
});

Dismiss on Tap Outside

import React from 'react';
import {
  View,
  TextInput,
  TouchableWithoutFeedback,
  Keyboard,
  StyleSheet,
} from 'react-native';

const DismissKeyboardHOC = ({ children }) => (
  <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
    {children}
  </TouchableWithoutFeedback>
);

const FormScreen = () => {
  return (
    <DismissKeyboardHOC>
      <View style={styles.container}>
        <TextInput
          style={styles.input}
          placeholder="Name"
        />
        <TextInput
          style={styles.input}
          placeholder="Email"
        />
      </View>
    </DismissKeyboardHOC>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  input: {
    height: 40,
    borderWidth: 1,
    padding: 10,
    marginBottom: 20,
  },
});

Custom Hook for Keyboard State

import { useEffect, useState } from 'react';
import { Keyboard } from 'react-native';

const useKeyboard = () => {
  const [keyboardHeight, setKeyboardHeight] = useState(0);
  const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);

  useEffect(() => {
    const showSubscription = Keyboard.addListener('keyboardDidShow', (e) => {
      setKeyboardHeight(e.endCoordinates.height);
      setIsKeyboardVisible(true);
    });

    const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
      setKeyboardHeight(0);
      setIsKeyboardVisible(false);
    });

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

  return { keyboardHeight, isKeyboardVisible };
};

// Usage
const MyComponent = () => {
  const { keyboardHeight, isKeyboardVisible } = useKeyboard();

  return (
    <View style={{ paddingBottom: keyboardHeight }}>
      {/* Your content */}
    </View>
  );
};

Platform Differences

iOS

  • Supports keyboardWillShow, keyboardWillHide, keyboardWillChangeFrame events
  • Provides smooth animation curves with easing and duration
  • Includes startCoordinates in event data
  • Keyboard appearance can be customized per input

Android

  • Only supports keyboardDidShow and keyboardDidHide events
  • No keyboardWill* events (no pre-animation callbacks)
  • Keyboard behavior depends on android:windowSoftInputMode setting
  • Requires adjustResize or adjustPan mode for layout events on API < 30
// Platform-specific event handling
import { Platform } from 'react-native';

const eventType = Platform.select({
  ios: 'keyboardWillShow',
  android: 'keyboardDidShow',
});

const subscription = Keyboard.addListener(eventType, handler);

KeyboardAvoidingView

For automatic keyboard avoidance, use KeyboardAvoidingView component:
import { KeyboardAvoidingView, Platform } from 'react-native';

<KeyboardAvoidingView
  behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
  style={{ flex: 1 }}
>
  <TextInput placeholder="Type here..." />
</KeyboardAvoidingView>

Best Practices

Use keyboardWillShow on iOS and keyboardDidShow on Android for cross-platform compatibility:
const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
Always remove event listeners in cleanup functions to prevent memory leaks.
On Android, keyboard events may not fire if android:windowSoftInputMode is set to adjustNothing in AndroidManifest.xml.

Common Use Cases

  • Adjust layout: Move content up when keyboard appears
  • Form validation: Submit form when keyboard is dismissed
  • Chat interfaces: Scroll to bottom when keyboard shows
  • Floating buttons: Reposition buttons above keyboard
  • Custom keyboard accessories: Add custom toolbars above keyboard

Build docs developers (and LLMs) love