React Native Animated仅以一种方式起作用?

时间:2020-04-19 13:58:43

标签: typescript react-native react-animated

我试图创建一个带有浮动占位符,更改背景,阴影等的文本输入。输入具有3种状态-空时,不空时以及焦点对准时。

您可以看到这些输入如何在我的网站上工作(仅在台式机上工作):https://www.treemotion.org/sign-in

您可以在这里通过https://www.icloud.com/photos/#0lqAi71mJLyev50Bdz_BmEmfA

在手机上查看它的工作方式。

一切都很流畅,而且效果很好,但是当我键入某些内容或将其删除并模糊输入时,动画将不起作用-只能在两种动画状态之间“切换”。

TextField.tsx:

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

const styles = StyleSheet.create({
    TextFieldWrapper: {
      borderRadius: 4, 
      position: 'relative', 
      marginTop: 20,
      width: 280,
      shadowOffset: { width: 0, height: 0},
      shadowColor: '#000000',
      shadowRadius: 10,
      elevation: 5,
    },
    TextField: {
      width: 280,
      paddingTop: 30,
      paddingLeft: 10,
      paddingRight: 10,
      paddingBottom: 10,
      fontSize: 18,
      fontWeight: 'bold',
      borderRadius: 4
    },
    TextFieldLabel: {
      position: 'absolute',
      left: 10
    }
  })

const TextField: React.FC<{ secureText: boolean, placeholder: string }> = ({secureText, placeholder}) => {
    const [value, setValue] = useState<string>('')
    const inputFocusAnimation = new Animated.Value(0)
    const inputContentAnimation = new Animated.Value(0)
    const emailLabelMarginTop = inputContentAnimation.interpolate({
        inputRange: [0, 1],
        outputRange: [20, 10]
    })
    const emailLabelFontSize = inputContentAnimation.interpolate({
        inputRange: [0, 1],
        outputRange: [18, 14]
    })
    const textFieldBackground = inputFocusAnimation.interpolate({
        inputRange: [0, 1],
        outputRange: ['rgba(242,242,242,1)', 'rgba(255,255,255,1)']
    })
    const textFieldShadow = inputFocusAnimation.interpolate({
        inputRange: [0, 1],
        outputRange: [0, .2]
    })
    function handleFocus() {
        Animated.timing(
            inputFocusAnimation,
            {
                toValue: 1,
                duration: 300
            }
        ).start()
        if(!value) {
            Animated.timing(
                inputContentAnimation,
                {
                    toValue: 1,
                    duration: 300
                }
            ).start()
        }
    }
    function handleBlur() {
        Animated.timing(
            inputFocusAnimation,
            {
                toValue: 0,
                duration: 300
            }
        ).start()
        if(!value) {
            Animated.timing(
                inputContentAnimation,
                {
                    toValue: 0,
                    duration: 300
                }
            ).start()
        }
    }
    return (
        <Animated.View style={{...styles.TextFieldWrapper, backgroundColor: textFieldBackground, shadowOpacity: textFieldShadow}}>
          <TextInput secureTextEntry={secureText} style={styles.TextField} placeholder=' ' onFocus={() => handleFocus()} onBlur={() => handleBlur()} onChangeText={(e: string) => setValue(e)}></TextInput>
          <Animated.Text style={{...styles.TextFieldLabel, top: emailLabelMarginTop, fontSize: emailLabelFontSize}}>{placeholder}</Animated.Text>
        </Animated.View>
    )
}

export default TextField

我还试图像这样在useEffect中“管理”这些动画:

useEffect(() => {
    ...
  }, [focus, value])    

但是我无法使其正常工作,所以我决定保留第一选择。有什么想法吗?

0 个答案:

没有答案