iPhone X上的KeyboardAvoidingView重叠屏幕

时间:2017-12-13 17:06:44

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

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

该组件如下所示:

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

是否有更好的方法来确定keyboardVerticalOffset应该是什么,而不是硬编码值?还有什么我可以用组件放置做不同的事情吗?我愿意接受任何建议。

iPhone 8

enter image description here

iPhone X

enter image description here

4 个答案:

答案 0 :(得分:8)

这是由iphoneX的状态栏高度不同引起的。 (如果您在模拟器中使用⌘Y切换&#39; in-call&#39;状态栏,您也会遇到与其他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>
    );
  }
}

答案 1 :(得分:3)

您是否正在使用反应导航?这可能会受到react-navigation标题的影响。标头的高度在不同的移动屏幕尺寸上有所不同。您需要获取标题的高度并将其传递给keyboardVerticalOffset道具。

<mat-form-field>
  <input matInput [matDatepicker]="picker" placeholder="Choose a date">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker opened="true"></mat-datepicker>
</mat-form-field>

答案 2 :(得分:2)

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

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

答案 3 :(得分:0)

所以我做了一个快速检查,鉴于我对如何在原生iOS中执行此操作的理解,并且看起来在较新版本的本机反应中,您可以相对容易地做到这一点。

根据您的灵活性需求,似乎有几种选择。

首先,您是否尝试过使用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