React-Native解决键盘遮挡问题(Keyboard遮挡问题)

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

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


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


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

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

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

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

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

[javascript]  view plain  copy
 
  1. import React, { Component, PropTypes} from 'react';  
  2. import {  
  3.   StyleSheet, View, Keyboard, LayoutAnimation  
  4. } from 'react-native';  
  5.   
  6. export default class InputBoard extends Component {  
  7.   constructor(props) {  
  8.     super(props);  
  9.     this.state={  
  10.       marginTop: 0,  
  11.     };  
  12.     this.keyboardShow = false;//当前键盘的状态,显示与否  
  13.     this.baseLayout = null;  
  14.     this.config = {  
  15.       duration: 150,  
  16.       create: {  
  17.         type: LayoutAnimation.Types.easeOut,  
  18.         property: LayoutAnimation.Properties.opacity,  
  19.       },  
  20.       update: {  
  21.         type: LayoutAnimation.Types.easeInEaseOut,  
  22.       }  
  23.     };  
  24.     this.basePos = null;  
  25.   }  
  26.   static propTypes = {  
  27.     spaceHeight: PropTypes.number, //固定增加高度  
  28.   }  
  29.   static defaultProps = {  
  30.     spaceHeight: 0,  
  31.   }  
  32.   componentWillMount() {  
  33.     this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow'this._keyboardDidShow.bind(this));  
  34.     this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide'this._keyboardDidHide.bind(this));  
  35.   }  
  36.   componentDidMount() {  
  37.     if (this.root){  
  38.       this.root.measure((ox, oy, width, height, px, py)=>{  
  39.         this.basePos = {  
  40.           ox: ox,  
  41.           oy: oy,  
  42.           width: width,  
  43.           height: height,  
  44.           px: px,  
  45.           py: py  
  46.         };  
  47.         console.log(this.basePos);  
  48.       });  
  49.     }   
  50.   }  
  51.   componentWillUnmount() {  
  52.     this.keyboardDidShowListener.remove();  
  53.     this.keyboardDidHideListener.remove();  
  54.   }  
  55.   _keyboardDidShow(e) {//当键盘弹起来  
  56.     this.keyboardShow = true;  
  57.     // let moveY = -(e.startCoordinates.height-this.baseLayout.y-this.baseLayout.height-this.props.spaceHeight);  
  58.     // if (moveY > 0){  
  59.     //   console.log("did show", e, 'move y: ' + moveY);  
  60.     //   LayoutAnimation.configureNext(this.config);  
  61.     //   this.setState({  
  62.     //     marginTop: moveY   
  63.     //   });  
  64.     // }  
  65.   
  66.     this.root.measure((ox, oy, width, height, px, py)=>{  
  67.       if (this.basePos)  
  68.       this.basePos = {  
  69.         ox: ox,  
  70.         oy: oy,  
  71.         width: width,  
  72.         height: height,  
  73.         px: px,  
  74.         py: py  
  75.       };  
  76.       let moveY = -(e.startCoordinates.height-this.basePos.py-this.props.spaceHeight);  
  77.       if (moveY > 0){  
  78.         console.log("did show", e, 'move y: ' + moveY);  
  79.         LayoutAnimation.configureNext(this.config);  
  80.         this.setState({  
  81.           marginTop: moveY   
  82.         });  
  83.       }  
  84.     });  
  85.   }  
  86.   _keyboardDidHide(e) {//当键盘收起后  
  87.     this.keyboardShow = false;  
  88.     if (this.state.marginTop != 0){  
  89.       LayoutAnimation.configureNext(this.config);  
  90.       console.log("did hide", e);  
  91.       this.setState({  
  92.         marginTop: 0,  
  93.       });  
  94.     }  
  95.   }  
  96.   onLayout(event){  
  97.     // if (event.nativeEvent.target == ReactNative.findNodeHandle(this.root))  
  98.     if (this.baseLayout == null){  
  99.       this.baseLayout = event.nativeEvent.layout;  
  100.     }  
  101.   }  
  102.   render() {  
  103.     console.log('render board');  
  104.     return (  
  105.       {this.root = r}}   
  106.         style={[styles.container, this.props.style, {marginTop: this.state.marginTop}]}  
  107.         onLayout={this.onLayout.bind(this)} />  
  108.     );  
  109.   }  
  110. }  
  111.   
  112. const styles = StyleSheet.create({  
  113.     container:{  
  114.     }  
  115. });  

然后使用:

[html]  view plain  copy
 
  1. <TextInput style={styles.textInput} />  
  2. <InputBoard spaceHeight={44}/>//textInput的高度是44.  

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

你可能感兴趣的:(】)