React Native中AnimatedTextInput点击后软键盘立即关闭如何解决?
问题根因
你将AnimatedTextInput的创建逻辑放在了TextField组件内部,每次组件的isFocused状态更新触发重渲染时,都会生成一个全新的AnimatedTextInput组件实例,原有输入框会被卸载、新输入框重新挂载,导致原有的输入焦点丢失,软键盘就会自动关闭。
修复方案
第一步:把AnimatedTextInput的创建移到组件外部
全局只需要创建一次动画封装组件,不需要每次组件渲染重复生成:
// 移到组件外部定义 const AnimatedTextInput = Animated.createAnimatedComponent(TextInput) const TextField = (props) => { // 原有组件逻辑,删掉内部的AnimatedTextInput定义 }
第二步:修正onFocus回调的参数传递
你当前的onFocus回调没有传递原生事件参数,有可能拦截了输入框的默认焦点行为,调整为:
<AnimatedTextInput style={[style, styles.input, { paddingTop: paddingTop, paddingBottom: paddingBottom }]} {...restOfProps} onFocus={handleFocus} onBlur={handleBlur} ref={refInput} />
可选兜底方案
如果调整后还有偶现的焦点丢失问题,可以在handleFocus里手动强制输入框保持焦点:
const handleFocus = (input) => { console.log('here') setIsFocused(true); refInput.current?.focus() }
完整修正后的代码
import React, { useRef } from 'react'; import { Animated, StyleSheet, Text, TextInput, View } from 'react-native'; // 全局定义一次AnimatedTextInput const AnimatedTextInput = Animated.createAnimatedComponent(TextInput) const styles = StyleSheet.create({ input: { padding: 24, borderColor: 'transparent', borderWidth: 1, borderRadius: 4, fontFamily: 'Avenir-Medium', fontSize: 16, backgroundColor: '#F8F8F8', }, labelContainer: { position: 'absolute', left: 16, top: 9, paddingHorizontal: 8, }, label: { color: '#ABB4BD', fontFamily: 'Avenir-Heavy', fontSize: 12, }, }) const TextField = (props) => { const { label, style, ...restOfProps } = props; const [isFocused, setIsFocused] = React.useState(false); const opacity = useRef(new Animated.Value(0)).current; const paddingTop = useRef(new Animated.Value(20)).current; const paddingBottom = useRef(new Animated.Value(20)).current; const refInput = useRef(); React.useEffect(() => { Animated.timing( paddingBottom, { useNativeDriver: false, toValue: isFocused ? 10 : 20, duration: 200, } ).start(); Animated.timing( paddingTop, { useNativeDriver: false, toValue: isFocused ? 30 : 20, duration: 200, } ).start(); Animated.timing( opacity, { useNativeDriver: false, toValue: isFocused ? 1 : 0, duration: 200, } ).start(); }, [isFocused]) const handleFocus = (input) => { console.log('here') setIsFocused(true); refInput.current?.focus() } const handleBlur = () => { console.log('there') setIsFocused(false); } return ( <View> <AnimatedTextInput style={[style, styles.input, { paddingTop: paddingTop, paddingBottom: paddingBottom }]} {...restOfProps} onFocus={handleFocus} onBlur={handleBlur} ref={refInput} /> <Animated.View style={[styles.labelContainer, { opacity: opacity}]}> <Text style={styles.label}>{label}</Text> </Animated.View> </View> ) }; export default TextField;
内容的提问来源于stack exchange,提问作者Brettins
相关产品推荐
相关产品推荐

