這篇文章主要介紹了React-Native如何解決鍵盤(pán)遮擋問(wèn)題,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
創(chuàng)新互聯(lián)是一家專(zhuān)業(yè)提供澄邁企業(yè)網(wǎng)站建設(shè),專(zhuān)注與成都做網(wǎng)站、網(wǎng)站制作、H5響應(yīng)式網(wǎng)站、小程序制作等業(yè)務(wù)。10年已為澄邁眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專(zhuān)業(yè)網(wǎng)站設(shè)計(jì)公司優(yōu)惠進(jìn)行中。在開(kāi)發(fā)中經(jīng)常遇到需要輸入的地方,RN給我們提過(guò)的TextInput雖然好用,可惜并沒(méi)有處理遮擋問(wèn)題。
很多時(shí)候鍵盤(pán)彈出來(lái)都會(huì)遮擋住編輯框,讓人很頭疼。
本來(lái)想在js.coach 庫(kù)里面找一找第三方的插件,看到最好的一個(gè)就是React-native-keyboard-spacer了,然而我們還差一個(gè)東西,那就是獲取鍵盤(pán)的高度。
這個(gè)我也查了半天并沒(méi)有提供,獲取沒(méi)找到吧。于是只好自己寫(xiě)原生模塊去獲取鍵盤(pán)的高度了。
關(guān)于原生iOS獲取鍵盤(pán)高度我就不多說(shuō)了,網(wǎng)上一大堆,我直接貼上我的代碼,自己根據(jù)RN寫(xiě)的原生模塊:
// // KeyboardHeight.h // Jicheng6 // // Created by guojicheng on 16/11/7. // Copyright © 2016年 Facebook. All rights reserved. // #import#import "RCTEventEmitter.h" #import "RCTBridgeModule.h" @interface KeyboardHeight : RCTEventEmitter -(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 { //獲取鍵盤(pán)的高度 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*)supportedEvents { return @[@"heightChanged"]; } -(void)heightChanged:(int)height { [self sendEventWithName:@"heightChanged" body:[NSNumber numberWithUnsignedInt:height]]; } @end
這里其實(shí)我前面的博客也說(shuō)過(guò),一開(kāi)始我想的是通過(guò)RCT_REMAP_METHOD去獲得高度,可惜在鍵盤(pán)第一次彈出的時(shí)候,并不是彈出之后的高度,獲取之后依然是0,所以添加了一個(gè)監(jiān)聽(tīng)函數(shù)heightChanged,當(dāng)記錄的值和改變的值不一致時(shí),調(diào)用監(jiān)聽(tīng)函數(shù),將值傳給JS端。這樣就可以在檢測(cè)變化之后JS端做相應(yīng)的變化。
好了,原生模塊封裝好了,接下來(lái)看js方面,這個(gè)也是老話(huà)題了,前面的博客都說(shuō)了,直接貼代碼:
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();//這里我是處理高度的 }
這里已經(jīng)拿到高度,接下來(lái)就好辦了,就是加減問(wèn)題。
我們需要拿到輸入框在屏幕中的位置,然后和鍵盤(pán)的高度做比較,輸入框的位置我們通過(guò)onLayout獲?。?/p>
onLayoutParent(event){ if (this.orgLayoutParent == null){//獲取的父組件的位置,因?yàn)橐玫接?jì)算 this.orgLayoutParent = event.nativeEvent.layout; } console.log('parent layout: ', event.nativeEvent.layout); } onLayoutMail(event){//獲取輸入框的位置,這個(gè)位置是相對(duì)父組件的位置,所以上面需要獲得父組件的 this.layoutMail = event.nativeEvent.layout; } onFocusMail(event){ this.focusName = 'mail';//定義一個(gè)標(biāo)識(shí),可以區(qū)分不同輸入框 this.changeMarginTop();//統(tǒng)一處理高度的函數(shù) } onSubmitMail(){ drawLayout.setKBMoveY(0);//當(dāng)輸入完畢時(shí),重置回原來(lái)的狀態(tài) } changeMarginTop(){//計(jì)算移動(dòng)的距離 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{//不對(duì)的置零處理 drawLayout.setKBMoveY(0); } } render() { return (); } //這里獲取的是相對(duì)位置哦 //點(diǎn)擊回車(chē)時(shí)的調(diào)用,這里可以根據(jù)需求去做 發(fā)送
如果你是當(dāng)前一個(gè)組件一個(gè)頁(yè)面,就沒(méi)必要像我這樣做了,加了一個(gè)global,去記錄它們的祖父組件(主要是整個(gè)頁(yè)面向上移動(dòng))
距離我們也都算好了,接下來(lái)就是給drawLayout加一個(gè)動(dòng)畫(huà),然后動(dòng)起來(lái)不要那么突兀。
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),//設(shè)置動(dòng)畫(huà)的初始值 }; global.drawLayout = this;//這里將自己保存到global里面,方便它的子組件調(diào)用 } setKBMoveY(y){ Animated.timing(//這里用的是timing均勻變化,具體的參數(shù),可以參考RN的文檔,寫(xiě)的很詳細(xì)了,這里就不啰嗦了。 this.state.kbShowY,{ toValue: y,//變化到目的位置 delay: 250,//延時(shí)250毫秒 }, ).start();//開(kāi)始 } componentWillUnmount() { global.drawLayout = null;//降這個(gè)值賦值為空 } render() { return (//使用Animated.View ); } }
這就大功告成了。接著截圖看看效果,雖然有動(dòng)畫(huà),沒(méi)法弄?jiǎng)討B(tài)圖
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“React-Native如何解決鍵盤(pán)遮擋問(wèn)題”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián)建站,關(guān)注創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線(xiàn),公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。