RajnishCoder
RajnishCoder

Reputation: 3725

How to detect when keyboard is opened or closed in React Native

How to detect if user close the keyboard in react native, I want to call a function when user closed the keyboard.

and if you can answer to detect keyboard is open too it will be appreciated, thanks.

I'm on the react native latest version 0.56

Upvotes: 109

Views: 142395

Answers (10)

Radu
Radu

Reputation: 21

I think it's more simpler than using useEffect or other stuff. TextInput provides methods onFocus and onBlur.

import {TextInput} from "react-native";
    
const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);

<TextInput 
  value={someValue}
  onFocus={() => setIsKeyboardVisible(true)}
  onBlur={() => setIsKeyboardVisible(false)}
/>

Upvotes: 2

Moh .S
Moh .S

Reputation: 2090

Improved version of @Khemraj 's answer (which worked great for me) with bound methods to the instance in order to be able to update the component's state from the listener and re-render.

import React, { Component } from 'react';
import { Keyboard, TextInput } from 'react-native';

class Example extends Component {

  state = {
      keyboardState: 'closed'
  }

  componentWillMount () {
    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow);
    this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
  }

  componentWillUnmount () {
    this.keyboardDidShowListener.remove();
    this.keyboardDidHideListener.remove();
  }

  _keyboardDidShow = () => {
    this.setState({
        keyboardState: 'opened'
    });
  }

  _keyboardDidHide = () => {
    this.setState({
        keyboardState: 'closed'
    });
  }

  render() {
    return (
      <TextInput
        onSubmitEditing={Keyboard.dismiss}
      />
    );
  }
}

Upvotes: 9

Alex Nolasco
Alex Nolasco

Reputation: 19456

I came across the usekeyboard hook found in @react-native-community/hooks

E.g.

import { useKeyboard } from '@react-native-community/hooks'
    
const keyboard = useKeyboard()
    
console.log('keyboard isKeyboardShow: ', keyboard.keyboardShown)
console.log('keyboard keyboardHeight: ', keyboard.keyboardHeight)

Source: https://github.com/react-native-community/hooks/blob/master/src/useKeyboard.ts

Upvotes: 11

Vinit S
Vinit S

Reputation: 422

2023 Update

If you are using React native 0.71 or later you can use Keyboard.isVisible()

Example

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

const Example = () => {
  return (
    <View style={style.container}>
      <TextInput
        style={style.input}
        placeholder="Click here…"
        onSubmitEditing={Keyboard.dismiss}
      />
      
      {Keyboard.isVisible() && <Text>Keyboard is visible</Text>}
    </View>
  );
};

const style = StyleSheet.create({
  container: {
    flex: 1,
    padding: 36,
  },
  input: {
    padding: 10,
    borderWidth: 0.5,
    borderRadius: 4,
  },
});

export default Example;

Upvotes: 19

halbano
halbano

Reputation: 1305

I wrapped this up in a hook:

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

export const useKeyboardVisible = () => {
  const [isKeyboardVisible, setKeyboardVisible] = useState(false);

  useEffect(() => {
    const keyboardDidShowListener = Keyboard.addListener(
      'keyboardDidShow',
      () => {
        setKeyboardVisible(true);
      },
    );
    const keyboardDidHideListener = Keyboard.addListener(
      'keyboardDidHide',
      () => {
        setKeyboardVisible(false);
      },
    );

    return () => {
      keyboardDidHideListener.remove();
      keyboardDidShowListener.remove();
    };
  }, []);

  return isKeyboardVisible;
};

The hook returns a boolean flag that can be used to apply logic conditionally or run any other effect needed.

Upvotes: 31

Jack Bridger
Jack Bridger

Reputation: 165

I used a small remix to the great answer from @halbano that may be useful to consider depending on your situation

export default function useKeyboardOffsetHeight(): number {
  const [keyBoardOffsetHeight, setKeyboardOffsetHeight] = useState(0);

  useEffect(() => {
    const keyboardWillShowListener = Keyboard.addListener(
      "keyboardWillShow",
      (e) => {
        setKeyboardOffsetHeight(e.endCoordinates.height);
      }
    );
    const keyboardWillHideListener = Keyboard.addListener(
      "keyboardWillHide",
      () => {
        setKeyboardOffsetHeight(0);
      }
    );

    return () => {
      keyboardWillHideListener.remove();
      keyboardWillShowListener.remove();
    };
  }, []);

  return keyBoardOffsetHeight;
}

keyBoardOffsetHeight vs isKeyboardVisible

I used integer keyBoardOffsetHeight instead of boolean isKeyboardVisible . Since it's often useful to move some of your other components based on the keyboard size. The offset is either 0 (hidden) or Y > 0 pixels (it is shown). Then I can use that in styling like so:

  const keyBoardOffsetHeight = useKeyboardOffsetHeight();
...
    <View
      style={{
        bottom: keyBoardOffsetHeight,
      }}
    >

keyboardWillShow vs keyboardDidShow

Secondly, I use keyboardWillShow events so that I can anticipate the keyboard appearing and fire my UI changes earlier.

The keyboardDidShow event fires once the keyboard has already appeared.

I also used keyboardWillHide instead of keyboardDidHide based on the same reasoning.

Upvotes: 2

Khemraj Sharma
Khemraj Sharma

Reputation: 58944

1. You can use Keyboard class from facebook.

Here is a sample code.

import React, { Component } from 'react';
import { Keyboard, TextInput } from 'react-native';

class Example extends Component {
  componentWillMount () {
    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow);
    this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
  }
    
  componentWillUnmount () {
    this.keyboardDidShowListener.remove();
    this.keyboardDidHideListener.remove();
  }
    
  _keyboardDidShow () {
    alert('Keyboard Shown');
  }
    
  _keyboardDidHide () {
    alert('Keyboard Hidden');
  }
    
  render() {
    return (
      <TextInput
        onSubmitEditing={Keyboard.dismiss}
      />
    );
  }
}

###2. You can use some other npm dependency also, like react-native-keyboard-listener.

Import the component into the file you want to use it:

import KeyboardListener from 'react-native-keyboard-listener';

Use the component directly in your code. The component won't render anything

<View>
  <KeyboardListener
    onWillShow={() => { this.setState({ keyboardOpen: true }); }}
    onWillHide={() => { this.setState({ keyboardOpen: false }); }}
  />
</View>

To install this dependency run below command.

npm install --save react-native-keyboard-listener

Choose any you feel more convenient.

Upvotes: 124

Akshay I
Akshay I

Reputation: 4175

All the thing already avalable in react-native Keyboard class

import React, { Component } from 'react';
import { Keyboard, TextInput } from 'react-native';

class Example extends Component {

    componentDidMount() {
        this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow);
        this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
        this.keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', this._keyboardWillShow);
        this.keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', this._keyboardWillHide);
    }

    componentWillUnmount() {
        this.keyboardDidShowListener.remove();
        this.keyboardDidHideListener.remove();
        this.keyboardWillShowListener.remove();
        this.keyboardWillHideListener.remove();
    }

    _keyboardWillShow() {
        console.log('Keyboard Showning')
    }

    _keyboardWillHide() {
        console.log('Keyboard Heding')
    }

    _keyboardDidShow() {
        alert('Keyboard Shown');
    }

    _keyboardDidHide() {
        alert('Keyboard Hidden');
    }

    render() {
        return (
            <TextInput
                onSubmitEditing={Keyboard.dismiss}
            />
        );
    }
}

Upvotes: 0

viz
viz

Reputation: 1277

MobX version:

import { observable } from 'mobx'
import { EmitterSubscription, Keyboard } from 'react-native'

class KeyboardStore {
  @observable isKeyboardVisible = false
  keyboardSubs: EmitterSubscription[] = []

  subKeyboard() {
    this.keyboardSubs = [
      Keyboard.addListener('keyboardDidShow', () => this.isKeyboardVisible = true),
      Keyboard.addListener('keyboardDidHide', () => this.isKeyboardVisible = false),
    ]
  }

  unsubKeyboard() {
    this.keyboardSubs.forEach(sub => sub.remove())
    this.keyboardSubs = []
  }
}

and inside top level App component

  useEffect(() => {
    store.subKeyboard()
    return () => {
      store.unsubKeyboard()
    }
  }, [])

and check anywhere in your app with store.isKeyboardVisible.

Upvotes: 1

5-10
5-10

Reputation: 2141

Thank you guys for your answers. Here is the hooks version if someone is interested:

const [isKeyboardVisible, setKeyboardVisible] = useState(false);

 useEffect(() => {
    const keyboardDidShowListener = Keyboard.addListener(
      'keyboardDidShow',
      () => {
        setKeyboardVisible(true); // or some other action
      }
    );
    const keyboardDidHideListener = Keyboard.addListener(
      'keyboardDidHide',
      () => {
        setKeyboardVisible(false); // or some other action
      }
    );

    return () => {
      keyboardDidHideListener.remove();
      keyboardDidShowListener.remove();
    };
  }, []);

Upvotes: 214

Related Questions