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

Posted

技术标签:

【中文标题】如何在 React Native 中检测键盘何时打开或关闭【英文标题】:How to detect when keyboard is opened or closed in React Native 【发布时间】:2019-01-07 10:05:13 【问题描述】:

如何检测用户是否在本机反应中关闭键盘,我想在用户关闭键盘时调用一个函数。

如果您能回答以检测键盘是否打开,我们将不胜感激,谢谢。

我在 react native 最新 version 0.56

【问题讨论】:

【参考方案1】:

1。您可以使用来自 facebook 的 Keyboard class

这是一个示例代码。

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 谢谢人。 @Khemraj 为什么我不能在函数 _keyboardDidShow 或 _keyboardDidHide 中设置状态? @Khemraj 需要注意的是,选项 2 不再适用于 android 我在我的应用程序中添加了Keyboard.addListener('keyboardDidShow', alert('keyboard'));,它一打开就会触发。在网络视图和我的 Android 设备上都是一样的。任何想法我做错了什么? @stefanS 是的。 alert('keyboard') 在您绑定处理程序时正在执行。要在触发处理程序时触发警报,请使用 Keyboard.addListener('keyboardDidShow', () =&gt; alert('keyboard'));【参考方案2】:

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

【讨论】:

【参考方案3】:

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

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

【讨论】:

嗨@5-10。我在我的应用程序中使用了这个确切的代码,但由于某种原因,这两个事件都没有被触发。我在清单文件中使用带有android:windowSoftInputMode="adjustResize" 的RN 版本0.63.4。什么可能导致它无法正常运行?谢谢。 在 RN 0.63.4 上按预期工作,没有任何清单更改。 当我尝试这个时,我得到以下错误:ReferenceError: Can't find variable: useEffect,有什么原因吗? 有点晚了,但@yem 你需要:import React, useEffect, useState from "react"import Keyboard from "react-native"【参考方案4】:

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检查您应用中的任何位置。

【讨论】:

【参考方案5】:

所有已经在 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
            />
        );
    

【讨论】:

【参考方案6】:

自定义挂钩:

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

export function useKeyboard() 
  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();
    ;
  , []);

  return isKeyboardVisible;

用法:

import  useKeyboard  from './useKeyboard';
    
const isKeyBoardOpen = useKeyboard();

【讨论】:

完美。谢谢【参考方案7】:

我在@react-native-community/hooks 中发现了usekeyboard 钩子

例如

import  useKeyboard  from '@react-native-community/hooks'

const keyboard = useKeyboard()

console.log('keyboard isKeyboardShow: ', keyboard.keyboardShown)
console.log('keyboard keyboardHeight: ', keyboard.keyboardHeight)

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

【讨论】:

很好的解决方案,但获取当前键盘状态似乎有延迟

以上是关于如何在 React Native 中检测键盘何时打开或关闭的主要内容,如果未能解决你的问题,请参考以下文章

键盘打开时TextInput不可见Expo React Native

使用React Native的MapView,我如何确定何时到达最终拖动目的地?

在 react-native 文本输入中检测粘贴事件

在 Modal 中防止键盘关闭 React Native

如何判断用户何时在 React-Native 中回答了 iOS 通知权限请求

使用 react-native-sensors 检测抖动设备事件?