本文介绍了React-Native键盘遮挡问题,分享给大家
在开发中经常遇到需要输入的地方,RN给我们提过的TextInput虽然好用,可惜并没有处理遮挡问题。
很多时候键盘弹出来都会遮挡住编辑框,让人很头疼。
本来想在js.coach 库里面找一找第三方的插件,看到最好的一个就是React-native-keyboard-spacer了,然而我们还差一个东西,那就是获取键盘的高度。
这个我也查了半天并没有提供,获取没找到吧。于是只好自己写原生模块去获取键盘的高度了。
关于原生iOS获取键盘高度我就不多说了,网上一大堆,我直接贴上我的代码,自己根据RN写的原生模块:
// // KeyboardHeight.h // Jicheng6 // // Created by guojicheng on 16/11/7. // Copyright © 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 © 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 "htmlcode">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> ); } }这就大功告成了。接着截图看看效果,虽然有动画,没法弄动态图
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。