React Native中如何让TextInput悬浮在键盘上方?
问题:TextInput获取焦点时无法悬浮在键盘上方
我想要实现TextInput获取焦点时悬浮在键盘上方,但当前用Keyboard监听的方式存在e.endCoordinates.height数值偏差,导致输入框被键盘部分或完全遮挡,也没找到适配现有布局的KeyboardAvoidingView用法。
解决方案
1. 修复Keyboard监听错误
原代码中keyboardDidHideListener未绑定事件,会导致卸载时报错,需补充绑定keyboardDidHide事件,同时可按需保留键盘高度监听逻辑。
2. 改用KeyboardAvoidingView适配布局
无需手动计算键盘高度,用KeyboardAvoidingView包裹输入区域,结合平台差异设置behavior属性(iOS用padding,Android用height),配合ScrollView确保内容可滚动,避免布局挤压。
3. 简化输入框定位逻辑
移除手动设置position: absolute和bottom: keyboardHeight的复杂逻辑,交给原生组件自动处理布局,解决设备适配偏差问题。
修改后的SignUpScreen代码
import { useNavigation } from "@react-navigation/native"; import React, { useState, useEffect, useRef } from "react"; import { ImageBackground, Keyboard, StyleSheet, Text, View, useWindowDimensions, KeyboardAvoidingView, ScrollView, Platform } from "react-native"; import { COLORS } from "../../assets/Colors/Colors"; import CustomButton from "../../components/CustomButton"; import CustomInput from "../../components/CustomInput"; import SocialSignInButtons from "../../components/SocialSignInButtons"; const SignUpScreen = () => { const [username, setUsername] = useState(""); const [email, setEmail] = useState(""); const window = useWindowDimensions(); const navigation = useNavigation(); const textInput1 = useRef(); useEffect(() => { setTimeout(() => { textInput1.current?.focus(); }, 0); // 修复键盘隐藏监听 const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => { // 按需添加键盘隐藏后的逻辑 }); const keyboardDidShowListener = Keyboard.addListener( "keyboardDidShow", (e) => { // 若仍需获取键盘高度可保留此逻辑,否则可移除 // setKeyboardHeight(e.endCoordinates.height); } ); return () => { keyboardDidHideListener.remove(); keyboardDidShowListener.remove(); }; }, []); const onRegisterPressed = () => { navigation.navigate("SignUp2"); }; const onSignInPressed = () => { navigation.navigate("SignIn"); }; const handleChange = (e, type) => { eval(`set${type}`)(e); }; return ( <ImageBackground resizeMode="stretch" source={require("../../assets/AppCustomBackgroundsFrench/SignUpFR.png")} style={styles.imageBackground} > <ScrollView contentContainerStyle={styles.scrollContent} keyboardShouldPersistTaps="handled" showsVerticalScrollIndicator={false} > <Text style={styles.title}>S'inscrire</Text> {/* 用KeyboardAvoidingView包裹输入区域 */} <KeyboardAvoidingView style={styles.inputContainer} behavior={Platform.OS === 'ios' ? 'padding' : 'height'} keyboardVerticalOffset={Platform.OS === 'ios' ? 60 : 0} // 根据实际布局调整偏移量 > <CustomInput ref={textInput1} onChangeText={(e) => handleChange(e, "Username")} placeholder="Username" value={username} /> <CustomInput onChangeText={(e) => handleChange(e, "Email")} placeholder="Email" value={email} /> </KeyboardAvoidingView> <CustomButton text="Suivant" onPress={onRegisterPressed} type="PRIMARY" /> <SocialSignInButtons /> <CustomButton text="Have an account? Sign In" onPress={onSignInPressed} type="TERTIARY" /> </ScrollView> </ImageBackground> ); }; const styles = StyleSheet.create({ imageBackground: { flex: 1, width: '100%', height: '100%', }, scrollContent: { flexGrow: 1, alignItems: "center", paddingTop: window.height * 0.34, paddingBottom: 20, paddingHorizontal: 20, }, title: { fontSize: 24, fontWeight: "bold", color: "#360d59", marginBottom: 30, alignSelf: 'flex-start', }, inputContainer: { width: '100%', alignItems: 'center', marginBottom: 40, }, }); export default SignUpScreen;
修改后的CustomInput代码
import { View, Text, TextInput, StyleSheet, Platform } from "react-native"; import React, { forwardRef, useState } from "react"; import { COLORS } from "../../assets/Colors/Colors"; const CustomInput = forwardRef( ( { onFocus = () => {}, onBlur = () => {}, label, style, ...props }, ref ) => { const [isOnFocus, setIsOnFocus] = useState(false); return ( <View style={[{ width: "100%" }, style]}> {label && <Text style={styles.subtitle}>{label}</Text>} <View style={[ styles.container, { borderColor: isOnFocus ? "yellow" : COLORS.input_Border_Violet }, ]} > <TextInput ref={ref} autocorrect={false} style={styles.input} {...props} onFocus={() => { onFocus(); setIsOnFocus(true); }} onBlur={() => { onBlur(); setIsOnFocus(false); }} /> </View> </View> ); } ); const styles = StyleSheet.create({ container: { backgroundColor: "white", width: "80%", borderRadius: 15, borderWidth: 2, marginVertical: 10, }, input: { paddingHorizontal: 10, paddingVertical: Platform.OS === 'ios' ? 15 : 12, }, subtitle: { color: COLORS.background, fontSize: 16, fontWeight: "bold", alignSelf: 'flex-start', paddingLeft: '10%', }, }); export default CustomInput;
关键说明
- KeyboardAvoidingView:根据平台自动调整布局方式,
keyboardVerticalOffset可根据导航栏、安全区域高度微调,确保输入框不被遮挡。 - ScrollView:包裹所有内容,键盘弹出时内容可滚动,避免底部按钮被挤压;
keyboardShouldPersistTaps="handled"允许点击输入框外区域时保持键盘打开(按需调整)。 - 移除手动定位:放弃监听键盘高度设置绝对定位的方式,依赖原生组件自动适配不同设备的键盘高度,解决数值偏差问题。
内容的提问来源于stack exchange,提问作者Rémi-Antoine Joron
相关产品推荐
相关产品推荐

