Animated state changes without cycling values using interpolation

Viewed 44

I'm trying to implement a simple color transition in react native. The current use case is for an Animated.TextInput, I want the backgroundColor to transition depending on the state. Let's say the component can have the following visual states:

state description
normal unfocussed input field
error unfocussed input field with an error
warning unfocussed input field with a warning
focus focussed input field disregarding the error/warning flags

A simplified version of such component:

import React, { useState, useEffect } from 'react'
import { Animated, TextInput as RNTextInput } from 'react-native'

const AnimatedTextInput = Animated.createAnimatedComponent(RNTextInput)

interface Props {
    errorMessage?: string
    warningMessage?: string
}

enum IndicatorState {
    Normal,
    Error,
    Warning,
    Focus
}

export const TextInput: React.FunctionComponent<Props> = (props) => {
    const [isInFocus, setIsInFocus] = useState(false)
    
    useEffect(() => {
        Animated.timing(indicatorStateAnim, {
            toValue: getIndicatorState(),
            duration: 100,
            useNativeDriver: false
        })
    }, [props.errorMessage, props.warningMessage, isInFocus])

    const getIndicatorState = (): IndicatorState => {
        if (isInFocus) return IndicatorState.Focus
        if (props.errorMessage) return IndicatorState.Error
        if (props.warningMessage) return IndicatorState.Error
        return IndicatorState.Normal
    }

    const indicatorStateAnim = new Animated.Value(getIndicatorState())

    return (
        <AnimatedTextInput
            onFocus={() => setIsInFocus(true)}
            onBlur={() => setIsInFocus(false)}
            style={{
                backgroundColor: indicatorStateAnim.interpolate({
                    inputRange: [
                        IndicatorState.Normal,
                        IndicatorState.Error,
                        IndicatorState.Warning,
                        IndicatorState.Focus
                    ],
                    outputRange: [
                        '#e3e3e3',
                        '#ff0000',
                        '#ffff00',
                        '#0000ff'
                    ]
                })
            }}
        />
    )
}

Using this method switching between two states does transition but it does so by cycling through the interpolated values (as expected of course). A little diagram showing the logic and difference between the current – expected – situation and the desired outcome of transitions.

Possible transition graphed in current and desired situation:

Possible transition graphed in current and desired situation

Example of transition between states in current and desired situation:

Example of transition between states in current and desired situation

In short; I'm looking for a solution for transitioning between multiple visual states using an animation without cycling through interpolated values (a.k.a. disco input fields)

0 Answers
Related