如何在 React-Native 中获得键盘的高度?

Posted

技术标签:

【中文标题】如何在 React-Native 中获得键盘的高度?【英文标题】:How to get a height of a Keyboard in React-Native? 【发布时间】:2018-03-17 03:42:18 【问题描述】:

我在我的应用程序中使用 React-Navigation,该应用程序由具有多个屏幕的 StackNavigator 组成,其中一些屏幕具有带有 autoFocus=true 的 TextInput

问题:在这些屏幕上,当组件渲染时,屏幕的高度是在构造函数中设置的:

constructor(props) 
    super(props);
    this.state =  
        height: Dimensions.get('window').height,
    ;

但是,由于 TextInput 的 autoFocustrue,因此该屏幕上的键盘几乎在渲染后立即弹出屏幕上,导致组件重新渲染由于在 componentWillMount 中添加到 Keyboard 的 eventListener:

 componentWillMount() 
    this.keyboardWillShowListener = Keyboard.addListener(
        "keyboardWillShow",
        this.keyboardWillShow.bind(this)
    );


keyboardWillShow(e) 
    this.setState(
        height:
            Dimensions.get("window").height * 0.9 - e.endCoordinates.height
    );
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);

这会影响性能,我想避免不必要的重新渲染。

问题: 1. React-Navigation 的 ScreenProps 中是否可以设置键盘的动态高度(取决于设备)? 2. 是否可以对 React-Navigation 的 state.params 做同样的事情? 3. 除了使用KeyboardAvoidingView 或this module 之外,还有其他方法可以解决这个问题吗?

【问题讨论】:

【参考方案1】:

这就是我所做的:

如果应用有“授权/登录/注册屏幕”,那么:

    在 componentWillMount 中添加 KeyboardListeners 解释here:

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

    将autoFocus添加到页面上的电子邮件/电话号码/任何其他“第一个”TextInput,这样当屏幕加载时,键盘就会弹出。

    在用作键盘监听器的_keyboardDidShow 函数中,执行以下操作:

    _keyboardDidShow(e) 
        this.props.navigation.setParams(
            keyboardHeight: e.endCoordinates.height,
            normalHeight: Dimensions.get('window').height, 
            shortHeight: Dimensions.get('window').height - e.endCoordinates.height, 
        ); 
    
    

    Dimensions 是 React-Native 的一个 API,不要忘记像导入任何 React-Native 组件一样导入它。

    之后,在重定向到下一页时,传递这些参数,不要忘记继续将它们传递到其他屏幕,以免丢失这些数据:

    this.props.navigation.navigate('pageName',  params: this.props.navigation.state.params );
    

【讨论】:

别忘了绑定this上下文,最好通过e => this._keyboardDidShow(e) 并且不要忘记取消订阅组件WillUnmount Keyboard.removeListener('keyboardDidShow', this._keyboardDidShow);中的键盘事件。 Keyboard.removeAllListeners(),如果您设置了多个事件侦听器 如何在没有基于keyboardDidShow 或keyboardDidHide 回调的android 中执行此操作? 此解决方案仅适用于已过时/不受欢迎的基于类的组件。【参考方案2】:

我还需要一个钩子,这就是我获得键盘高度的方法(很大程度上受到其他答案的启发),代码示例在 TypeScript 中:

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

export const useKeyboard = () => 
  const [keyboardHeight, setKeyboardHeight] = useState(0);

  function onKeyboardDidShow(e: KeyboardEvent)  // Remove type here if not using TypeScript
    setKeyboardHeight(e.endCoordinates.height);
  

  function onKeyboardDidHide() 
    setKeyboardHeight(0);
  

  useEffect(() => 
    const showSubscription = Keyboard.addListener('keyboardDidShow', onKeyboardDidShow);
    const hideSubscription = Keyboard.addListener('keyboardDidHide', onKeyboardDidHide);
    return () => 
      showSubscription.remove();
      hideSubscription.remove();
    ;
  , []);

  return keyboardHeight;
;

然后在你的组件中:

  const keyboardHeight = useKeyboard();
  console.log(keyboardHeight);

【讨论】:

这对我很有用。我需要使用 KeyboardAvoidingView 来替代嵌入在 ScrollView 中的 Flatlist,因为将 Flatlist 包装在 ScrollView 中存在冲突。就我而言,这是不可避免的,因为 Flatlist 是自发生成的,因此其他选项都不起作用。谢谢! 像魅力一样工作。非常感谢。 没有理由返回包含键盘高度的数组,只需返回keyboardHeight。不过钩子不错。 现在我们将在从addListener 返回的事件发射器上使用remove 方法。所以在useEffect中:const showEvent = Keyboard.addListener('keyboardDidShow',onKeyboardDidShow,); const hideEvent = Keyboard.addListener('keyboardDidHide',onKeyboardDidHide,); return () => showEvent.remove(); hideEvent.remove();;。抱歉格式化! @theneekz 好声音。我会更新答案。感谢您指出这一点。【参考方案3】:

对于那些仍在寻找now you can use hooks 答案的人。

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

//Then keyboard like this 

const keyboard = useKeyboard()

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

【讨论】:

我试过这个,但我找不到一个好地方可以打电话给useKeyboard 没有抱怨。你能详细说明应该在哪里工作吗? (不,***对我不起作用) @Lazerbeak12345,应该用在功能组件中。【参考方案4】:

只是想补充一下上述答案,使用keyboardWillShowkeyboardWillHide 而不是keyboardDidShowkeyboardDidHide 看起来会好得多。它只是运行得更快,因此看起来更流畅。

【讨论】:

下面为什么大家都用Did?也许他们不使用Will是有原因的? 我能想到的一个潜在原因是传递给keyboardDidShow/keyboardDidHide 的回调可能类似于componentDidMount(您将不想阻塞UI的操作放在这里),如果这些事件的Will 变体阻碍了键盘的实际显示和隐藏(尤其是在回调中执行昂贵的操作时),使用Did 将是更好的选择。就我而言,使用 Will 更好,因为我希望 UI 中发生我希望尽快发生的特定事情。 我使用了Did,因为我假设Will 我不会得到键盘的高度。不过我可能猜错了。 在我的测试中,Will 没有在 Android 上触发。因此,他们似乎想到了 Android。 @KevinAmiranoff 在 ios 上使用 Will 也带有键盘高度。 如果您必须在隐藏键盘上显示一些弹出窗口,AlertActionSheet,您必须将其放入 keyboardDidHide,因为在 keyboardWillHide 中执行会导致触发等副作用多次隐藏键盘并在弹出窗口关闭后再次显示键盘。

以上是关于如何在 React-Native 中获得键盘的高度?的主要内容,如果未能解决你的问题,请参考以下文章

如何获得 iOS 8.3 表情符号键盘高度?

react-native解决键盘自适应

在 iOS8 中无法获得正确的键盘高度值

在android中是否有任何方法可以获得设备虚拟键盘的高度

如何在 react-native 应用程序中更改 android 的键盘主题?

如何在 React-Native 应用程序中检索 iOS 状态栏高度?