【问题标题】:KeyboardAvoidingView overlapping screen on iPhone XiPhone X 上的 KeyboardAvoidingView 重叠屏幕
【发布时间】:2017-12-13 17:06:44
【问题描述】:

我目前有一个KeyboardAvoidingView,其中硬编码的keyboardVerticalOffset 为 64。这在 iPhone 上运行良好,但在 iPhone X 上短约 20 像素。

组件如下所示:

<KeyboardAvoidingView behavior='padding' keyboardVerticalOffset={ 64 }>
  <View style={ styles.messageList }>
    ...
  </View>
  <View style={ styles.messageInput }>
    ...
  </View>
</KeyboardAvoidingView>

有没有比硬编码一个值更好的方法来确定keyboardVerticalOffset 应该是什么?在组件放置方面我还可以做些什么不同的事情吗?我愿意接受任何建议。

iPhone 8

iPhone X

【问题讨论】:

  • 另一件要考虑的事情是,当您更改键盘类型时,键盘可以改变大小。我不熟悉如何在 reactNative 中处理它,但在本机 iOS 代码中,您将注册为 UIKeyboardWillChangeFrameNotification 通知的观察者。您将收到通知的 userInfo 将为您提供键盘框架的详细信息。 stackoverflow.com/a/35427662/3708242。但我不确定是否有办法在 react native 中捕获通知。
  • 你有没有想过解决这个问题?

标签: ios iphone react-native react-native-ios


【解决方案1】:

这是由于 iphoneX 的状态栏高度不同造成的。 (如果您在模拟器中使用 ⌘Y 切换“通话中”状态栏,其他 iPhone 也会遇到同样的问题)。

您可以获取状态栏高度并使用它来设置KeyboardAvoidingView 的keyboardVerticalOffset 值。 (在我们的例子中是 44 + statusBarHeight)

import React, {Component} from 'react';
import {KeyboardAvoidingView, NativeModules, StatusBarIOS} from 'react-native';

const {StatusBarManager} = NativeModules;

export class IOSKeyboardAvoidingView extends Component {

  state = {statusBarHeight: 0};

  componentDidMount() {
    StatusBarManager.getHeight((statusBarFrameData) => {
      this.setState({statusBarHeight: statusBarFrameData.height});
    });
    this.statusBarListener = StatusBarIOS.addListener('statusBarFrameWillChange', (statusBarData) => {
      this.setState({statusBarHeight: statusBarData.frame.height});
    });
  }

  componentWillUnmount() {
    this.statusBarListener.remove();
  }

  render() {
    const {style, children} = this.props;
    return (
      <KeyboardAvoidingView
        behavior="padding"
        keyboardVerticalOffset={44 + this.state.statusBarHeight}
        style={style}
      >{children}
      </KeyboardAvoidingView>
    );
  }
}

【讨论】:

    【解决方案2】:

    【讨论】:

      【解决方案3】:

      我使用了一个自定义组件来克服这种情况。

      import React from "react";
      import {Animated, Keyboard} from "react-native";
      
      export default class KeyboardAwareComponent extends React.Component {
      
          constructor(props) {
              super(props)
              this.keyboardHeight = new Animated.Value(0);
          }
      
          componentWillMount () {
              this.keyboardWillShowSub = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow);
              this.keyboardWillHideSub = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide);
          }
      
          componentWillUnmount() {
              this.keyboardWillShowSub.remove();
              this.keyboardWillHideSub.remove();
          }
      
          keyboardWillShow = (event) => {
              Animated.parallel([
                  Animated.timing(this.keyboardHeight, {
                      duration: event.duration,
                      toValue: event.endCoordinates.height,
                  })
              ]).start();
          };
      
          keyboardWillHide = (event) => {
              Animated.parallel([
                  Animated.timing(this.keyboardHeight, {
                      duration: event.duration,
                      toValue: 0,
                  })
              ]).start();
          };
      
          render(){
              const {children, style, ...props} = this.props
              return(
                  <Animated.View style={[{flex:1,alignItems:'center',paddingBottom: this.keyboardHeight},style]} {...props}>
                      {children}
                  </Animated.View>
              );
          }
      
      }
      

      只需使用组件“KeyboardAwareComponent”作为任何页面的根组件。它会在键盘显示或隐藏时自动调整视图。

      示例:---

      YourComponent extends React.Component{
          render(){
              <KeyboardAwareComponent>
                  {Your child views}
              </KeyboardAwareComponent>
          }
      }
      

      【讨论】:

        【解决方案4】:

        所以我做了一个快速检查,鉴于我对如何在原生 iOS 中执行此操作的理解,并且似乎在较新版本的 react native 中,您可以相对轻松地执行此操作。

        似乎确实有几种选择,具体取决于您的灵活性需求。

        首先,您是否尝试过使用KeyboardAvoidView 而不是标准容器View 而不指定keyboardVerticalOffset

        另一个为您提供更多控制权的选项(类似于我在本机 iOS 应用程序中所做的)是使用 Keyboard 模块在键盘事件上创建侦听器。

          componentWillMount () {
            this.keyboardWillShowSub = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow);
            this.keyboardWillChangeSub = Keyboard.addListener('keyboardWillChangeFrame', this.keyboardWillChange);
            this.keyboardWillHideSub = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide);
          }
        
          componentWillUnmount() {
            this.keyboardWillShowSub.remove();
            this.keyboardWillChangeSub.remove();
            this.keyboardWillHideSub.remove();
          }
        

        这将允许您从事件参数中获取键盘高度:

        keyboardWillShow = (event) => {
            Animated.parallel([
              Animated.timing(this.keyboardHeight, {
                duration: event.duration,
                toValue: event.endCoordinates.height,
              }),
              Animated.timing(this.imageHeight, {
                duration: event.duration,
                toValue: IMAGE_HEIGHT_SMALL,
              }),
            ]).start();
          };
        

        对 keyboardWillChange 和 keyboardWillHide 重复类似的操作。

        有关您的选项的更好、更详细的说明,请参阅此页面: https://medium.freecodecamp.org/how-to-make-your-react-native-app-respond-gracefully-when-the-keyboard-pops-up-7442c1535580

        我认为最好的第一个测试是在尝试添加代码来处理 keboard 事件之前尝试删除 keyboardVerticalOffset

        【讨论】:

        • 是的,我尝试过使用没有keyboardVerticalOffset 的KeyboardAvoidingView。如果没有keyboardVerticalOffset,键盘会完全覆盖“消息”部分。
        • 你运行的是最新版本的 react native 吗?如果没有,我会尝试更新以查看是否已解决。然后,我会尝试使用键盘事件的方法,您可以准确地看到键盘框架发生了什么,并适当地调整您的 UI 组件。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-01
        • 1970-01-01
        相关资源
        最近更新 更多