温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

React-Native如何解决键盘遮挡问题

发布时间:2021-07-20 09:39:21 来源:亿速云 阅读:203 作者:小新 栏目:web开发

这篇文章主要介绍了React-Native如何解决键盘遮挡问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

在开发中经常遇到需要输入的地方,RN给我们提过的TextInput虽然好用,可惜并没有处理遮挡问题。

很多时候键盘弹出来都会遮挡住编辑框,让人很头疼。

本来想在js.coach 库里面找一找第三方的插件,看到最好的一个就是React-native-keyboard-spacer了,然而我们还差一个东西,那就是获取键盘的高度。

这个我也查了半天并没有提供,获取没找到吧。于是只好自己写原生模块去获取键盘的高度了。

关于原生iOS获取键盘高度我就不多说了,网上一大堆,我直接贴上我的代码,自己根据RN写的原生模块:

//  // KeyboardHeight.h  // Jicheng6  //  // Created by guojicheng on 16/11/7.  // Copyright &copy; 2016年 Facebook. All rights reserved.  //    #import <UIKit/UIKit.h>  #import "RCTEventEmitter.h"  #import "RCTBridgeModule.h"    @interface KeyboardHeight : RCTEventEmitter<RCTBridgeModule>    -(void)heightChanged:(int)height;    @property (nonatomic, assign)int kbHeight;    @end
//  // KeyboardHeight.m  // Jicheng6  //  // Created by guojicheng on 16/11/7.  // Copyright &copy; 2016年 Facebook. All rights reserved.  //    #import "KeyboardHeight.h"    @implementation KeyboardHeight    RCT_EXPORT_MODULE();    - (instancetype)init  {   self = [super init];   if (self) {    self.kbHeight = 0;    [[NSNotificationCenter defaultCenter] addObserver:self                         selector:@selector(keyboardDidShow:)                           name:UIKeyboardDidShowNotification                          object:nil];   }   return self;  }    -(void)keyboardDidShow:(NSNotification*) aNotification  {   //获取键盘的高度   NSDictionary *userInfo = [aNotification userInfo];   NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];   CGRect keyboardRect = [aValue CGRectValue];   if (_kbHeight != keyboardRect.size.height){    _kbHeight = keyboardRect.size.height;    [self heightChanged:_kbHeight];   }  }    RCT_REMAP_METHOD(getKBHeight,           resolver:(RCTPromiseResolveBlock)resolve           rejecter:(RCTPromiseRejectBlock)reject)  {   resolve([[NSNumber alloc]initWithInt:_kbHeight]);  }    - (NSArray<NSString *> *)supportedEvents  {   return @[@"heightChanged"];  }    -(void)heightChanged:(int)height  {   [self sendEventWithName:@"heightChanged" body:[NSNumber numberWithUnsignedInt:height]];  }    @end

这里其实我前面的博客也说过,一开始我想的是通过RCT_REMAP_METHOD去获得高度,可惜在键盘第一次弹出的时候,并不是弹出之后的高度,获取之后依然是0,所以添加了一个监听函数heightChanged,当记录的值和改变的值不一致时,调用监听函数,将值传给JS端。这样就可以在检测变化之后JS端做相应的变化。

好了,原生模块封装好了,接下来看js方面,这个也是老话题了,前面的博客都说了,直接贴代码:

import React, { Component } from 'react';  import {    AppRegistry,    StyleSheet,    Text,    View,    TouchableOpacity,    Alert,    TextInput,    PixelRatio,    Linking,    Keyboard,    NativeEventEmitter,  } from 'react-native';    var Dimensions = require('Dimensions');  var ScreenWidth = Dimensions.get('window').width;  var ScreenHeight = Dimensions.get('window').height;    var kbHeight = require('NativeModules').KeyboardHeight;  const kbHeightEvt = new NativeEventEmitter(kbHeight);
componentWillMount() {      this.heightChanged = kbHeightEvt.addListener('heightChanged', this._heightChanged.bind(this));    }    componentDidMount() {      }    componentWillUnmount() {      this.heightChanged.remove();    }    _heightChanged(data){      // console.log(data);      this.keyboardHeight = data;      this.changeMarginTop();//这里我是处理高度的    }

这里已经拿到高度,接下来就好办了,就是加减问题。

我们需要拿到输入框在屏幕中的位置,然后和键盘的高度做比较,输入框的位置我们通过onLayout获取:

onLayoutParent(event){      if (this.orgLayoutParent == null){//获取的父组件的位置,因为要用到计算        this.orgLayoutParent = event.nativeEvent.layout;      }      console.log('parent layout: ', event.nativeEvent.layout);    }    onLayoutMail(event){//获取输入框的位置,这个位置是相对父组件的位置,所以上面需要获得父组件的      this.layoutMail = event.nativeEvent.layout;    }    onFocusMail(event){      this.focusName = 'mail';//定义一个标识,可以区分不同输入框      this.changeMarginTop();//统一处理高度的函数    }    onSubmitMail(){      drawLayout.setKBMoveY(0);//当输入完毕时,重置回原来的状态    }    changeMarginTop(){//计算移动的距离      var layout = null;      if (this.focusName == 'mail'){        layout = this.layoutMail;      }      if (layout && this.orgLayoutParent.y + layout.y + layout.height > ScreenHeight - this.keyboardHeight){        drawLayout.setKBMoveY(-(this.orgLayoutParent.y + layout.y + layout.height - ScreenHeight + this.keyboardHeight));      }else{//不对的置零处理        drawLayout.setKBMoveY(0);      }    }    render() {      return (        <View style={[styles.container, this.props.style ? this.props.style : {}]} onLayout={this.onLayoutParent.bind(this)}>          <View style={[styles.viewStyle, {marginTop: 10}]} onLayout={this.onLayoutMail.bind(this)}>//这里获取的是相对位置哦            <TextInput style={styles.textInputStyle}              onChangeText={this.onTextChange.bind(this)}              value={this.state.emailPath}              placeholder={'请输入邮箱'}              onFocus={this.onFocusMail.bind(this)}//当获取到焦点时触发              onSubmitEditing={this.onSubmitMail.bind(this)}/>//点击回车时的调用,这里可以根据需求去做            <TouchableOpacity onPress={this.onSubmitSend.bind(this)}>              <View style={[styles.sendButtonView, {}]}>                <Text style={styles.sendButtonText}>                  发送                </Text>              </View>            </TouchableOpacity>          </View>        </View>      );    }

如果你是当前一个组件一个页面,就没必要像我这样做了,加了一个global,去记录它们的祖父组件(主要是整个页面向上移动)

距离我们也都算好了,接下来就是给drawLayout加一个动画,然后动起来不要那么突兀。

import React, { Component } from 'react';  import {   StyleSheet,   Text,   View,   TouchableOpacity,   Animated,  } from 'react-native';    import SendEmail from './SendEmail';    export default class DrawLayout extends Component {   constructor(props){    super(props);    this.state={     kbShowY: new Animated.Value(0),//设置动画的初始值    };    global.drawLayout = this;//这里将自己保存到global里面,方便它的子组件调用   }   setKBMoveY(y){    Animated.timing(//这里用的是timing均匀变化,具体的参数,可以参考RN的文档,写的很详细了,这里就不啰嗦了。     this.state.kbShowY,{      toValue: y,//变化到目的位置      delay: 250,//延时250毫秒     },    ).start();//开始   }   componentWillUnmount() {    global.drawLayout = null;//降这个值赋值为空   }      render() {    return (     <Animated.View style={[styles.container, {marginTop: this.state.kbShowY}]} >//使用Animated.View      <SendEmail style={{marginTop: 10}}/>     </Animated.View>    );   }  }

这就大功告成了。接着截图看看效果,虽然有动画,没法弄动态图

React-Native如何解决键盘遮挡问题  

React-Native如何解决键盘遮挡问题

感谢你能够认真阅读完这篇文章,希望小编分享的“React-Native如何解决键盘遮挡问题”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI