我在前面也写了一篇关于键盘遮挡问题的解决方案,这次的原理也差不多,不过在后续的研究中发现官方给了一个有意思的组件叫 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;
-
-
-
-
-
-
-
-
-
- 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 (this.baseLayout == null){
- this.baseLayout = event.nativeEvent.layout;
- }
- }
- render() {
- console.log('render board');
- return (
- {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,所以在样式上有一定的要求,不能使用固定的位置,否则计算的位置有误差,甚至是不动。