Плавающий ввод в React Native

Я пытаюсь создать плавающий ввод в React Native, но проблема в том, что мне нужно нажать на пустую область (красную область), чтобы заполнитель мог плавать и позволить мне писать внутри поля ввода.

Однако, если я попытаюсь нажать заголовок заполнителя, ничего не произойдет. Заполнитель не плавает, курсор не появляется, и я не могу писать.

это мой код


export default function SingleLineText({ onChange, placeholder, columnName, requiredInput, inputValue }) {
    const [value, setValue] = useState("");
    const moveText = useRef(new Animated.Value(0)).current;
    const schema = yup.object().shape({
        columnName: yup.string().required('You should enter this field.'),
    });

    const { control, handleSubmit, formState: { errors } } = useForm({
        resolver: yupResolver(schema),
        defaultValues: {
            columnName: inputValue ? inputValue : '',
        },
    });

    useEffect(() => {
        if (value !== "") {
            moveTextTop();
        } else if (value === "") {
            moveTextBottom();
        }
    }, [value])

    useEffect(() => {
        onChange(value)
    }, [value])

    const onChangeText = (text) => {
        setValue(text);
    };

    const onFocusHandler = () => {
        moveTextTop();
    };

    const onBlurHandler = () => {
        if (value === "") {
            moveTextBottom();
        }
    };

    const moveTextTop = () => {
        Animated.timing(moveText, {
            toValue: 1,
            duration: 200,
            useNativeDriver: true,
        }).start();
    };

    const moveTextBottom = () => {
        Animated.timing(moveText, {
            toValue: 0,
            duration: 200,
            useNativeDriver: true,
        }).start();
    };

    const yVal = moveText.interpolate({
        inputRange: [0, 2.5],
        outputRange: [4, -20],
    });

    const animStyle = {
        transform: [
            {
                translateY: yVal,
            },
        ],
    };
    return (
        <View style = {styles.container}>
            <Animated.View style = {[styles.animatedStyle, animStyle]}>
                <Text style = {styles.label}>{placeholder}</Text>
            </Animated.View>
            <Controller
                control = {control}
                rules = {{ requiredInput }}
                render = {({ field: { onChange, value, onBlur } }) => (
                    <TextInput
                        onBlur = {onBlurHandler}
                        value = {inputValue}
                        onChangeText = {onChangeText}
                        style = {styles.input}
                        onFocus = {onFocusHandler}
                    />
                )}
                name = {columnName}
            />
            {errors.columnName && <Text >{errors?.columnName?.message}</Text>}
        </View>
    )
}
const styles = StyleSheet.create({
    container: {
        height: 53,
        backgroundColor: Colors.lightGray,
        borderRadius: 8,
        paddingTop: 15,
        marginVertical: 5,
        paddingHorizontal: 18,
        borderColor: "#bdbdbd",
        width: "100%",
        justifyContent: "center",
    },
    input: {
        fontFamily: FONTS.PoppinsRegular,
        fontSize: 18,
        height: 53,
    },
    label: {
        paddingVertical: 5,
        fontFamily: FONTS.PoppinsRegular,
        color: Colors.SmokeBlue,
        fontSize: 15,
    },
    animatedStyle: {
        top: 4,
        left: 15,
        position: 'absolute',
        borderRadius: 90,
        zIndex: 10000,
    },
    errorMessage: {
        color: Colors.Red,
        fontFamily: FONTS.PoppinsMedium,
        fontSize: 10,
    }
});

🤔 А знаете ли вы, что...
JavaScript можно использовать для создания анимаций и игр на веб-страницах.


86
1

Ответ:

Решено

Попробуй это

Оберните Animated.View в Pressable и используйте функцию onFocusHandler в onPress.

     <View style = {styles.container}>
        <Pressable onPress = {onFocusHandler}>
             <Animated.View style = {[styles.animatedStyle, animStyle]}>
                 <Text style = {styles.label}>{placeholder}</Text>
             </Animated.View>
        </Pressable>
        <Controller
            control = {control}
            rules = {{ requiredInput }}
            render = {({ field: { onChange, value, onBlur } }) => (
                <TextInput
                    onBlur = {onBlurHandler}
                    value = {inputValue}
                    onChangeText = {onChangeText}
                    style = {styles.input}
                    onFocus = {onFocusHandler}
                />
            )}
            name = {columnName}
        />
        {errors.columnName && <Text >{errors?.columnName?.message}</Text>}
    </View>