如何在React Native中检测键盘的打开或关闭

102
如何在React Native中检测用户是否关闭了键盘,我想在用户关闭键盘时调用一个函数。如果您能回答如何检测键盘是否打开,将不胜感激,谢谢。我使用最新的React Native版本0.56。
10个回答

198

谢谢你们的回答。这是钩子版本,如果有人感兴趣:

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();
    };
  }, []);

1
嗨@5-10。我在我的应用程序中使用了这个完全相同的代码,但由于某种原因,两个事件都没有被触发。我正在使用RN版本0.63.4,并在清单文件中使用android:windowSoftInputMode =“adjustResize”。可能是什么原因导致它无法正常工作?谢谢。 - sj_959
1
在 RN 0.63.4 上正常工作,无需进行任何清单更改。 - Gilad M
当我尝试这样做时,我会得到以下错误:ReferenceError: Can't find variable: useEffect,有什么原因吗? - yem
3
有点晚了,但是 @yem 你需要这样做:import React, { useEffect, useState } from "react",还有 import { Keyboard } from "react-native" - Guille Acosta

122

1. 您可以使用来自Facebook的Keyboard类

以下是示例代码。

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. 你也可以使用其他的npm依赖,比如 react-native-keyboard-listener

将该组件导入到您想要使用它的文件中:

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

在您的代码中直接使用该组件。该组件不会呈现任何内容。

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

要安装此依赖项,请运行以下命令。

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

选择你觉得更方便的任何一种。


第一个我希望它能像超人一样工作:D 谢谢。 - RajnishCoder
@Khemraj 为什么我不能在函数_keyboardDidShow或_keyboardDidHide中使用setState? - Miko
@Khemraj 需要注意的是,在安卓系统上,选项2已经不再可用。 - Devin Haslam
我在我的应用程序中添加了Keyboard.addListener('keyboardDidShow', alert('keyboard'));,并且它会在我打开应用程序时立即触发。这在Web视图和我的Android设备上都是一样的。有什么想法我做错了什么吗? - stefanS
1
@stefanS 是的。alert('keyboard') 在绑定处理程序时被执行。要在处理程序触发时触发警报,请使用 Keyboard.addListener('keyboardDidShow', () => alert('keyboard')); - grossvogel
附加信息: 使用 .bind(this) 可以使用 setState 或 this。此外,this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow.bind(this)); - JxDarkAngel

23

我用一个钩子包装了这个:

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;
};

这个钩子返回一个布尔标志,可以用于有条件地应用逻辑或运行任何其他所需效果。


谢谢,这是一个很好的答案 - 谢谢!对我来说更好的一个小修改是使用keyboardWillShow和keyboardWillHide事件。这些事件在键盘将要出现时触发,因此可以同时移动文本输入框并加载键盘。 - Jack Bridger
1
谢谢你的评论伙计!是的,那很有道理,你可能需要两个不同的钩子来覆盖应用程序中的不同情况:useKeyboardDidShow和useKeyboardWillShow可能是它们的良好命名。 - halbano
哦,是的,那是个好主意! - Jack Bridger
1
这是一个非常方便的解决方案 - 感谢 @halbano! - Joshua Book
请注意:要在您的React或React Native应用程序中使用此作为钩子,请使用import { useKeyboardVisible } from "../../useKeyboardVisible";,然后使用const isKeyboardVisible = useKeyboardVisible();如果您使用console.log(isKeyboardVisible),您将获得您的"true""false"状态。 - Chukwuebuka Nwoba
1
事半功倍 - undefined

9

1
好的解决方案,但似乎存在获取当前键盘状态的延迟。 - Patrick Lafferty

8

这是改进版本的@Khemraj答案(对我非常有用),使用绑定方法到实例中,以便可以从侦听器更新组件状态并重新呈现。

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}
      />
    );
  }
}

8

2023年更新

如果您正在使用React Native 0.71或更高版本,您可以使用Keyboard.isVisible()

示例


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;


1
非常好的答案。谢谢你,编码比设置事件/监听器要少得多。 - Adam

2

我对@halbano的出色回答进行了小小的改编,这可能取决于您的情况而有所帮助。

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;
}

keyBoardOffsetHeightisKeyboardVisible

我使用整数keyBoardOffsetHeight而不是布尔值isKeyboardVisible。因为根据键盘的大小移动其他组件通常很有用。偏移量为0(隐藏)或Y > 0像素(显示)。然后我可以在样式中使用它,如下所示:

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

keyboardWillShowkeyboardDidShow

其次,我使用keyboardWillShow事件来预测键盘的出现并尽早触发UI更改。

keyboardDidShow事件在键盘已经出现后触发。

我也基于同样的原因使用了keyboardWillHide而不是keyboardDidHide


keyboardWillShow没有为我提供高度。必须使用keyboardDidShow。 WillShow是意图/动作;DidShow将具有该动作的结果。 - Dawit

1

MobX版本:

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 = []
  }
}

并且在顶层的App组件内部

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

并且可以使用store.isKeyboardVisible在应用程序中的任何位置进行检查。


1

我认为这比使用useEffect或其他东西更简单。 TextInput提供了onFocus和onBlur方法。

import {TextInput} from "react-native";

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

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

0

在React Native的Keyboard类中已经有所有需要的东西了。

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}
            />
        );
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接