如何在React Native中实现带动画效果的自定义浮动标签TextInput
你需要借助React Native自带的Animated动画API,结合聚焦状态、输入值状态控制标签的位移动画,具体修改如下:
第一步:导入依赖
先在文件顶部引入需要的核心API:
import { useState, useRef, useEffect } from 'react'; import { View, TextInput, Text, StyleSheet, Animated, Easing } from 'react-native';
第二步:修改组件逻辑
完整的组件代码调整如下:
export default function InputBox(props) { const [isFocused, setIsFocused] = useState(false); const [inputValue, setInputValue] = useState(props.defaultValue || ''); // 动画值:0代表标签在输入框内,1代表标签上浮到外部 const labelAnimation = useRef(new Animated.Value(inputValue ? 1 : 0)).current; // 监听状态变化触发动画 useEffect(() => { Animated.timing(labelAnimation, { toValue: isFocused || inputValue.trim() !== '' ? 1 : 0, duration: 200, // 动画时长可自定义 easing: Easing.inOut(Easing.ease), useNativeDriver: false, }).start(); }, [isFocused, inputValue, labelAnimation]); const handleFocus = () => setIsFocused(true); const handleBlur = () => setIsFocused(false); const handleChangeText = (text) => { setInputValue(text); props.onChangeText?.(text); }; // 标签动态样式插值 const labelAnimatedStyle = { transform: [ { translateY: labelAnimation.interpolate({ inputRange: [0, 1], outputRange: [18, 0], // 可根据设计稿调整位移数值 }), }, ], fontSize: labelAnimation.interpolate({ inputRange: [0, 1], outputRange: [13, 10], }), // 不需要聚焦变色可删掉color配置 color: labelAnimation.interpolate({ inputRange: [0, 1], outputRange: [COLORS.GREY, isFocused ? COLORS.PRIMARY : COLORS.GREY], }), }; return ( <View style={[styles.container, { // 可选:聚焦时高亮边框 borderColor: isFocused ? COLORS.PRIMARY : COLORS.GREY_BORDER }]}> <Animated.Text style={[styles.label, labelAnimatedStyle]}> {props.label} </Animated.Text> <TextInput style={styles.input} autoCapitalize="none" defaultValue={props.defaultValue} onChangeText={handleChangeText} keyboardType={props.keyboardType} editable={props.editable} onFocus={handleFocus} onBlur={handleBlur} value={inputValue} /> </View> ); }
第三步:调整样式
重点修改容器和标签的定位规则,预留标签上浮的空间:
const styles = StyleSheet.create({ container: { marginBottom: 20, backgroundColor: COLORS.WHITE, paddingTop: 15, // 增加顶部内边距放浮动标签 paddingHorizontal: 10, borderWidth: 1, borderColor: COLORS.GREY_BORDER, borderRadius: 2, position: 'relative', }, icon: { width: 40, justifyContent: 'center', alignItems: 'center', }, input: { fontFamily: FONT_FAMILY.primaryMedium, fontSize: 13, height: 35, color: COLORS.BLACK, }, label: { fontFamily: FONT_FAMILY.primary, color: COLORS.GREY, position: 'absolute', // 绝对定位不占用输入框空间 left: 10, // 和父容器水平内边距保持一致 }, });
可根据实际设计稿调整位移、字体大小的数值,匹配预期视觉效果。
内容的提问来源于stack exchange,提问作者Juhi Kukreja
相关产品推荐
相关产品推荐

