React Native(Expo)自定义按钮隐藏键盘后TextInput焦点异常求助
React Native(Expo)自定义键盘关闭按钮焦点问题解决方案
问题现象
使用硬件Esc键关闭键盘时,TextInput会完全失去焦点,后续滚动内容松开手指后键盘保持收起(符合预期);但点击调用Keyboard.dismiss()的自定义工具栏按钮时,键盘虽收起,TextInput仍保留焦点,导致每次滚动松开手指后键盘都会重新弹出。
解决方案
核心是在关闭键盘的同时,主动让所有TextInput失去焦点,模拟硬件Esc键的完整行为。具体步骤如下:
1. 引入useRef钩子并创建输入框引用
在组件顶部导入useRef,并创建存储两个TextInput实例的引用:
import { useRef, useEffect, useState } from "react"; export default function WriteScreen() { // ... 原有代码 const titleInputRef = useRef(null); const contentInputRef = useRef(null); // ... 原有代码 }
2. 给每个TextInput绑定ref属性
修改UI布局中的两个TextInput,分别绑定对应的引用:
<TextInput ref={titleInputRef} style={styles.title} placeholder="제목" placeholderTextColor="#999" /> <TextInput ref={contentInputRef} style={styles.content} placeholder="내용" placeholderTextColor="#999" multiline textAlignVertical="top" />
3. 更新dismissKeyboard函数
修改关闭键盘的逻辑,先让所有输入框失去焦点,再调用Keyboard.dismiss():
const dismissKeyboard = () => { // 让标题输入框失焦 titleInputRef.current?.blur(); // 让内容输入框失焦 contentInputRef.current?.blur(); // 收起键盘 Keyboard.dismiss(); };
完整修改后的组件代码
import { MaterialIcons } from "@expo/vector-icons"; import { useHeaderHeight } from "expo-router/react-navigation"; import { useRef, useEffect, useState } from "react"; import { Keyboard, KeyboardAvoidingView, Platform, Pressable, StyleSheet, TextInput, View, } from "react-native"; export default function WriteScreen() { const headerHeight = useHeaderHeight(); const [isKeyboardVisible, setIsKeyboardVisible] = useState(false); const titleInputRef = useRef(null); const contentInputRef = useRef(null); useEffect(() => { const showEvent = Platform.OS === "ios" ? "keyboardWillShow" : "keyboardDidShow"; const hideEvent = Platform.OS === "ios" ? "keyboardWillHide" : "keyboardDidHide"; const show = Keyboard.addListener(showEvent, () => setIsKeyboardVisible(true), ); const hide = Keyboard.addListener(hideEvent, () => setIsKeyboardVisible(false), ); return () => { show.remove(); hide.remove(); }; }, []); const dismissKeyboard = () => { titleInputRef.current?.blur(); contentInputRef.current?.blur(); Keyboard.dismiss(); }; return ( <KeyboardAvoidingView style={styles.container} behavior={Platform.OS === "ios" ? "padding" : "height"} keyboardVerticalOffset={headerHeight} > <TextInput ref={titleInputRef} style={styles.title} placeholder="제목" placeholderTextColor="#999" /> <TextInput ref={contentInputRef} style={styles.content} placeholder="내용" placeholderTextColor="#999" multiline textAlignVertical="top" /> <View style={styles.toolbar}> {isKeyboardVisible ? ( <Pressable style={styles.keyboardDismissButton} onPress={dismissKeyboard} hitSlop={8} accessibilityRole="button" > <MaterialIcons name="keyboard-hide" size={22} /> </Pressable> ) : null} </View> </KeyboardAvoidingView> ); } const styles = StyleSheet.create({ container: { flex: 1, paddingHorizontal: 16, backgroundColor: "#fff", }, flex: { flex: 1, }, scrollContent: { flexGrow: 1, }, title: { fontSize: 20, fontWeight: "bold", paddingVertical: 12, }, content: { flexGrow: 1, fontSize: 16, textAlignVertical: "top", }, toolbar: { height: 48, flexDirection: "row", justifyContent: "flex-end", alignItems: "center", borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: "#ddd", }, toolbarButton: { padding: 8, }, keyboardDismissButton: { padding: 4, borderRadius: 10, alignItems: "center", justifyContent: "center", }, });
原理说明
Keyboard.dismiss()仅负责收起系统键盘,但不会改变TextInput的焦点状态。而硬件Esc键会同时触发键盘收起和输入框失焦两个动作。通过手动调用blur()方法,我们让自定义按钮的行为和Esc键完全一致,从而避免滚动时键盘意外弹出的问题。
内容的提问来源于stack exchange,提问作者wjsyuwls
相关产品推荐
相关产品推荐

