如何在React Native中创建自定义动画浮动标签TextInput?

a64a0gku  于 2023-03-31  发布在  React
关注(0)|答案(2)|浏览(135)

我在React Native中创建了一个TextInput

但我希望标签在isFocused或填充一些值时具有动画:

如果value为null或空,则标签必须在输入内,否则标签必须移动到输入外并带有动画
我的代码:

export default function InputBox(props) {
  return (
    <View style={styles.container}>
      <Text style={styles.label}>{props.label}</Text>
      <TextInput
        style={styles.input}
        autoCapitalize="none"
        defaultValue={props.defaultValue}
        onChangeText={props.onChangeText}
        keyboardType={props.keyboardType}
        editable={props.editable}
      />
    </View>
  );
}

款式:

const styles = StyleSheet.create({
  container: {
    marginBottom: 20,
    backgroundColor: COLORS.WHITE,
    paddingTop: 5,
    paddingHorizontal: 10,
    borderWidth: 1,
    borderColor: COLORS.GREY_BORDER,
    borderRadius: 2,
  },
  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,
    fontSize: 10,
  },
});
plicqrtu

plicqrtu1#

如果你想制作你自己的动画,你可以将标签Text Package 到一个Animated.View组件中,给予动画。
试试这个:

import React, { useEffect, useState, useRef } from "react";
import {
  View,
  StyleSheet,
  TextInput,
  Text,
  Animated,
  Pressable,
} from "react-native";

const TestScreen = () => {
  const [value, setValue] = useState("");
  const moveText = useRef(new Animated.Value(0)).current;

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

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

  const onFocusHandler = () => {
    if (value !== "") {
      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, 1],
    outputRange: [4, -20],
  });

  const animStyle = {
    transform: [
      {
        translateY: yVal,
      },
    ],
  };

  return (
    <View style={styles.container}>
      <Animated.View style={[styles.animatedStyle, animStyle]}>
        <Text style={styles.label}>Enter Your Name</Text>
      </Animated.View>
      <TextInput
        autoCapitalize={"none"}
        style={styles.input}
        value={value}
        onChangeText={(text: string) => onChangeText(text)}
        editable={true}
        onFocus={onFocusHandler}
        onBlur={onBlurHandler}
        blurOnSubmit
      />
    </View>
  );
};
export default TestScreen;

const styles = StyleSheet.create({
  container: {
    marginBottom: 20,
    marginTop: 20,
    backgroundColor: "#fff",
    paddingTop: 5,
    paddingHorizontal: 10,
    borderWidth: 1,
    borderColor: "#bdbdbd",
    borderRadius: 2,
    width: "90%",
    alignSelf: "center",
  },
  icon: {
    width: 40,
    justifyContent: "center",
    alignItems: "center",
  },
  input: {
    fontSize: 13,
    height: 35,
    color: "#000",
  },
  label: {
    color: "grey",
    fontSize: 10,
  },
  animatedStyle: {
    top: 5,
    left: 15,
    position: 'absolute',
    borderRadius: 90,
    zIndex: 10000,
  },
});

juzqafwq

juzqafwq2#

答案是好的,但是在这种情况下你可能不需要useEffect,它可以被重构为

import React, {useState, useRef} from 'react';
import {View, StyleSheet, TextInput, Text, Animated} from 'react-native';

const TestScreen = () => {
  const [value, setValue] = useState('');
  const moveText = useRef(new Animated.Value(0)).current;

  const onFocusHandler = () => {
    if (!value) {
      moveTextTop();
    }
  };
  const onBlur = () => {
    if (!value) {
      moveTextBottom();
    }
  };
  const onChangeText = (textValue: string) => {
    setValue(textValue);
    if (textValue !== '') {
      moveTextTop();
    } else 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, 1],
    outputRange: [4, -20],
  });

  const animStyle = {
    transform: [{translateY: yVal}],
  };

  return (
    <View style={styles.container}>
      <Animated.View style={[styles.animatedStyle, animStyle]}>
        <Text style={styles.label}>Enter Your Name</Text>
      </Animated.View>
      <TextInput
        value={value}
        onBlur={onBlur}
        style={styles.input}
        onFocus={onFocusHandler}
        onChangeText={onChangeText}
      />
    </View>
  );
};
export default TestScreen;

const styles = StyleSheet.create({
  container: {
    marginBottom: 20,
    marginTop: 20,
    backgroundColor: '#fff',
    paddingTop: 5,
    paddingHorizontal: 10,
    borderWidth: 1,
    borderColor: '#bdbdbd',
    borderRadius: 2,
    width: '90%',
    alignSelf: 'center',
  },
  icon: {
    width: 40,
    justifyContent: 'center',
    alignItems: 'center',
  },
  input: {
    fontSize: 13,
    height: 35,
    color: '#000',
  },
  label: {
    color: 'grey',
    fontSize: 10,
  },
  animatedStyle: {
    top: 5,
    left: 15,
    position: 'absolute',
    borderRadius: 90,
    zIndex: 10000,
  },
});

相关问题