詳解React-Native解決鍵盤遮擋問題(Keyboard遮擋問題)
本文介紹了React-Native鍵盤遮擋問題,分享給大家
在開發(fā)中經(jīng)常遇到需要輸入的地方,RN給我們提過的TextInput雖然好用,可惜并沒有處理遮擋問題。
很多時候鍵盤彈出來都會遮擋住編輯框,讓人很頭疼。
本來想在js.coach 庫里面找一找第三方的插件,看到最好的一個就是React-native-keyboard-spacer了,然而我們還差一個東西,那就是獲取鍵盤的高度。
這個我也查了半天并沒有提供,獲取沒找到吧。于是只好自己寫原生模塊去獲取鍵盤的高度了。
關(guān)于原生iOS獲取鍵盤高度我就不多說了,網(wǎng)上一大堆,我直接貼上我的代碼,自己根據(jù)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,所以添加了一個監(jiān)聽函數(shù)heightChanged,當(dāng)記錄的值和改變的值不一致時,調(diào)用監(jiān)聽函數(shù),將值傳給JS端。這樣就可以在檢測變化之后JS端做相應(yīng)的變化。
好了,原生模塊封裝好了,接下來看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();//這里我是處理高度的 }
這里已經(jīng)拿到高度,接下來就好辦了,就是加減問題。
我們需要拿到輸入框在屏幕中的位置,然后和鍵盤的高度做比較,輸入框的位置我們通過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';//定義一個標(biāo)識,可以區(qū)分不同輸入框 this.changeMarginTop();//統(tǒng)一處理高度的函數(shù) } onSubmitMail(){ drawLayout.setKBMoveY(0);//當(dāng)輸入完畢時,重置回原來的狀態(tài) } 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)}//當(dāng)獲取到焦點時觸發(fā) onSubmitEditing={this.onSubmitMail.bind(this)}/>//點擊回車時的調(diào)用,這里可以根據(jù)需求去做 <TouchableOpacity onPress={this.onSubmitSend.bind(this)}> <View style={[styles.sendButtonView, {}]}> <Text style={styles.sendButtonText}> 發(fā)送 </Text> </View> </TouchableOpacity> </View> </View> ); }
如果你是當(dāng)前一個組件一個頁面,就沒必要像我這樣做了,加了一個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),//設(shè)置動畫的初始值 }; global.drawLayout = this;//這里將自己保存到global里面,方便它的子組件調(diào)用 } setKBMoveY(y){ Animated.timing(//這里用的是timing均勻變化,具體的參數(shù),可以參考RN的文檔,寫的很詳細(xì)了,這里就不啰嗦了。 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> ); } }
這就大功告成了。接著截圖看看效果,雖然有動畫,沒法弄動態(tài)圖
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
react框架next.js學(xué)習(xí)之API?路由篇詳解
這篇文章主要為大家介紹了react框架next.js學(xué)習(xí)之API?路由篇詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09React.js組件實現(xiàn)拖拽排序組件功能過程解析
這篇文章主要介紹了React.js組件實現(xiàn)拖拽排序組件功能過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04React Native中導(dǎo)航組件react-navigation跨tab路由處理詳解
這篇文章主要給大家介紹了關(guān)于React Native中導(dǎo)航組件react-navigation跨tab路由處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10Native?Memory?Tracking追蹤區(qū)域示例分析
這篇文章主要為大家介紹了Native?Memory?Tracking追蹤區(qū)域示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11