Реагировать на Native Animated работает только одним способом? - PullRequest
0 голосов
/ 19 апреля 2020

Я пытался создать текстовый ввод с плавающим заполнителем, изменяя фон, тени и т. Д. c Вход имеет 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])    

Но я не мог заставить это работать хорошо, поэтому я решил остаться с первым вариантом. Есть идеи?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...