详解React-Native解决键盘遮挡问题(Keyboard遮挡问题)
发布时间 - 2026-01-11 02:19:28 点击率:次本文介绍了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 ? 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之key的使用和实践
# React key值的作用和使用详解
# React中使用collections时key的重要性详解
# ReactNative之键盘Keyboard的弹出与消失示例
# 详解React中key的作用
# 的是
# 好了
# 输入框
# 弹出
# 说了
# 我是
# 我也
# 我想
# 我就
# 让人
# 你是
# 最好的
# 就不
# 就好
# 不多
# 说过
# 给我们
# 这就
# 半天
# 就没
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
Laravel怎么进行浏览器测试_Laravel Dusk自动化浏览器测试入门
音响网站制作视频教程,隆霸音响官方网站?
如何在IIS中新建站点并配置端口与IP地址?
如何用AI帮你把自己的生活经历写成一个有趣的故事?
如何快速搭建支持数据库操作的智能建站平台?
Win11怎么修改DNS服务器 Win11设置DNS加速网络【指南】
Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】
如何在不使用负向后查找的情况下匹配特定条件前的换行符
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
JS实现鼠标移上去显示图片或微信二维码
html文件怎么打开证书错误_https协议的html打开提示不安全【指南】
Swift中switch语句区间和元组模式匹配
佛山企业网站制作公司有哪些,沟通100网上服务官网?
Laravel Eloquent:优雅地将关联模型字段扁平化到主模型中
三星网站视频制作教程下载,三星w23网页如何全屏?
Laravel如何集成Inertia.js与Vue/React?(安装配置)
如何挑选优质建站一级代理提升网站排名?
Laravel怎么判断请求类型_Laravel Request isMethod用法
Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】
Laravel如何实现邮件验证激活账户_Laravel内置MustVerifyEmail接口配置【步骤】
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
如何获取PHP WAP自助建站系统源码?
Laravel Fortify是什么,和Jetstream有什么关系
Win11关机界面怎么改_Win11自定义关机画面设置【工具】
夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化
浅谈Javascript中的Label语句
奇安信“盘古石”团队突破 iOS 26.1 提权
网站制作免费,什么网站能看正片电影?
Laravel Docker环境搭建教程_Laravel Sail使用指南
java中使用zxing批量生成二维码立牌
Laravel队列任务超时怎么办_Laravel Queue Timeout设置详解
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
Laravel如何处理表单验证?(Requests代码示例)
Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程
ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】
java获取注册ip实例
利用python获取某年中每个月的第一天和最后一天
Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出
公司门户网站制作流程,华为官网怎么做?
美食网站链接制作教程视频,哪个教做美食的网站比较专业点?
Laravel如何实现用户密码重置功能?(完整流程代码)
济南网站建设制作公司,室内设计网站一般都有哪些功能?
HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】
南京网站制作费用,南京远驱官方网站?
Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】
如何选择可靠的免备案建站服务器?

