React-Native如何解决键盘遮挡问题(react-native,web开发)

时间:2024-04-28 13:24:06 作者 : 石家庄SEO 分类 : web开发
  • TAG :

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

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

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

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

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

////KeyboardHeight.h//Jicheng6////Createdbyguojichengon16/11/7.//Copyright&copy;2016年Facebook.Allrightsreserved.//#import<UIKit/UIKit.h>#import"RCTEventEmitter.h"#import"RCTBridgeModule.h"@interfaceKeyboardHeight:RCTEventEmitter<RCTBridgeModule>-(void)heightChanged:(int)height;@property(nonatomic,assign)intkbHeight;@end
////KeyboardHeight.m//Jicheng6////Createdbyguojichengon16/11/7.//Copyright&copy;2016年Facebook.Allrightsreserved.//#import"KeyboardHeight.h"@implementationKeyboardHeightRCT_EXPORT_MODULE();-(instancetype)init{self=[superinit];if(self){self.kbHeight=0;[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(keyboardDidShow:)name:UIKeyboardDidShowNotificationobject:nil];}returnself;}-(void)keyboardDidShow:(NSNotification*)aNotification{//获取键盘的高度NSDictionary*userInfo=[aNotificationuserInfo];NSValue*aValue=[userInfoobjectForKey:UIKeyboardFrameEndUserInfoKey];CGRectkeyboardRect=[aValueCGRectValue];if(_kbHeight!=keyboardRect.size.height){_kbHeight=keyboardRect.size.height;[selfheightChanged:_kbHeight];}}RCT_REMAP_METHOD(getKBHeight,resolver:(RCTPromiseResolveBlock)resolverejecter:(RCTPromiseRejectBlock)reject){resolve([[NSNumberalloc]initWithInt:_kbHeight]);}-(NSArray<NSString*>*)supportedEvents{return@[@"heightChanged"];}-(void)heightChanged:(int)height{[selfsendEventWithName:@"heightChanged"body:[NSNumbernumberWithUnsignedInt:height]];}@end

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

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

importReact,{Component}from'react';import{AppRegistry,StyleSheet,Text,View,TouchableOpacity,Alert,TextInput,PixelRatio,Linking,Keyboard,NativeEventEmitter,}from'react-native';varDimensions=require('Dimensions');varScreenWidth=Dimensions.get('window').width;varScreenHeight=Dimensions.get('window').height;varkbHeight=require('NativeModules').KeyboardHeight;constkbHeightEvt=newNativeEventEmitter(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('parentlayout:',event.nativeEvent.layout);}onLayoutMail(event){//获取输入框的位置,这个位置是相对父组件的位置,所以上面需要获得父组件的this.layoutMail=event.nativeEvent.layout;}onFocusMail(event){this.focusName='mail';//定义一个标识,可以区分不同输入框this.changeMarginTop();//统一处理高度的函数}onSubmitMail(){drawLayout.setKBMoveY(0);//当输入完毕时,重置回原来的状态}changeMarginTop(){//计算移动的距离varlayout=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(<Viewstyle={[styles.container,this.props.style?this.props.style:{}]}onLayout={this.onLayoutParent.bind(this)}><Viewstyle={[styles.viewStyle,{marginTop:10}]}onLayout={this.onLayoutMail.bind(this)}>//这里获取的是相对位置哦<TextInputstyle={styles.textInputStyle}onChangeText={this.onTextChange.bind(this)}value={this.state.emailPath}placeholder={'请输入邮箱'}onFocus={this.onFocusMail.bind(this)}//当获取到焦点时触发onSubmitEditing={this.onSubmitMail.bind(this)}/>//点击回车时的调用,这里可以根据需求去做<TouchableOpacityonPress={this.onSubmitSend.bind(this)}><Viewstyle={[styles.sendButtonView,{}]}><Textstyle={styles.sendButtonText}>发送</Text></View></TouchableOpacity></View></View>);}

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

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

importReact,{Component}from'react';import{StyleSheet,Text,View,TouchableOpacity,Animated,}from'react-native';importSendEmailfrom'./SendEmail';exportdefaultclassDrawLayoutextendsComponent{constructor(props){super(props);this.state={kbShowY:newAnimated.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.Viewstyle={[styles.container,{marginTop:this.state.kbShowY}]}>//使用Animated.View<SendEmailstyle={{marginTop:10}}/></Animated.View>);}}

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

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

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

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:React-Native如何解决键盘遮挡问题的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:JavaScript严格模式下关于this的几种指向详解下一篇:

4 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18