React-Native键盘遮挡问题进阶发现

参考:http://blog.csdn.net/pz789as/article/details/53404352


我在前面也写了一篇关于键盘遮挡问题的解决方案,这次的原理也差不多,不过在后续的研究中发现官方给了一个有意思的组件叫 KeyboardAvoidingView。然后就动手去试了一试,然而效果并不好!具体用法可以参考这里:点击打开链接

不过随着RN的更新,这个官网肯定会解决的,但是在官方还没填坑前,还是得自己动手解决啦。


我前面博客的处理方法:点击打开链接


其实原理是要获取到键盘的高度和输入框的位置,然后去计算偏移位置就可以了。

那么今天这篇是写什么呢?

我前面的方法主要是自己写了原生的代码,然后获取键盘宽高,但是我今天才知道,原来RN的Keyboard组件已经有这个了,所以可以把之前方法中的原生部分可以剪掉了,毕竟还是官方的靠谱呀~

然后,今天的第二个发现就是RN中获取一个组件在屏幕的位置,这个以前我不知道,是通过组件和父组件的位置,去计算组件在屏幕的位置,这个的麻烦就是层次越深,越不好计算,你要传的数据就太多了,导致计算繁琐,不好得到正确的位置。今天我就告诉大家一个好方法,也是RN自带的叫measure。每个view都有这个属性,它里面就有6个参数,分别为ox,oy,width,height,px,py。这里的px,py就是组件在屏幕的位置啦!真是太棒啦~~

于是,我根据这些新发现,写了一个组件,在需要用的TextInput组件下面直接使用,就可以啦!直接贴代码好了:

import React, { Component, PropTypes} from 'react';
import {
  StyleSheet, View, Keyboard, LayoutAnimation
} from 'react-native';

export default class InputBoard extends Component {
  constructor(props) {
    super(props);
    this.state={
      marginTop: 0,
    };
    this.keyboardShow = false;//当前键盘的状态,显示与否
    this.baseLayout = null;
    this.config = {
      duration: 150,
      create: {
        type: LayoutAnimation.Types.easeOut,
        property: LayoutAnimation.Properties.opacity,
      },
      update: {
        type: LayoutAnimation.Types.easeInEaseOut,
      }
    };
    this.basePos = null;
  }
  static propTypes = {
    spaceHeight: PropTypes.number, //固定增加高度
  }
  static defaultProps = {
    spaceHeight: 0,
  }
  componentWillMount() {
    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow.bind(this));
    this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide.bind(this));
  }
  componentDidMount() {
    if (this.root){
      this.root.measure((ox, oy, width, height, px, py)=>{
        this.basePos = {
          ox: ox,
          oy: oy,
          width: width,
          height: height,
          px: px,
          py: py
        };
        console.log(this.basePos);
      });
    } 
  }
  componentWillUnmount() {
    this.keyboardDidShowListener.remove();
    this.keyboardDidHideListener.remove();
  }
  _keyboardDidShow(e) {//当键盘弹起来
    this.keyboardShow = true;
    // let moveY = -(e.startCoordinates.height-this.baseLayout.y-this.baseLayout.height-this.props.spaceHeight);
    // if (moveY > 0){
    //   console.log("did show", e, 'move y: ' + moveY);
    //   LayoutAnimation.configureNext(this.config);
    //   this.setState({
    //     marginTop: moveY 
    //   });
    // }

    this.root.measure((ox, oy, width, height, px, py)=>{
      if (this.basePos)
      this.basePos = {
        ox: ox,
        oy: oy,
        width: width,
        height: height,
        px: px,
        py: py
      };
      let moveY = -(e.startCoordinates.height-this.basePos.py-this.props.spaceHeight);
      if (moveY > 0){
        console.log("did show", e, 'move y: ' + moveY);
        LayoutAnimation.configureNext(this.config);
        this.setState({
          marginTop: moveY 
        });
      }
    });
  }
  _keyboardDidHide(e) {//当键盘收起后
    this.keyboardShow = false;
    if (this.state.marginTop != 0){
      LayoutAnimation.configureNext(this.config);
      console.log("did hide", e);
      this.setState({
        marginTop: 0,
      });
    }
  }
  onLayout(event){
    // if (event.nativeEvent.target == ReactNative.findNodeHandle(this.root))
    if (this.baseLayout == null){
      this.baseLayout = event.nativeEvent.layout;
    }
  }
  render() {
    console.log('render board');
    return (
      <View ref={(r)=>{this.root = r}} 
        style={[styles.container, this.props.style, {marginTop: this.state.marginTop}]}
        onLayout={this.onLayout.bind(this)} />
    );
  }
}

const styles = StyleSheet.create({
    container:{
    }
});

然后使用:

<TextInput style={styles.textInput} />
<InputBoard spaceHeight={44}/>//textInput的高度是44.

注意一点的是,我内部是使用的marginTop,所以在样式上有一定的要求,不能使用固定的位置,否则计算的位置有误差,甚至是不动。

如果谁可以给这个进行改良,希望可以发给我~哈哈


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏小败在路上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值