How do I animate the background color of a button in React Native?

Animation can be done using the Layout Animation or Animated API. LayoutAnimation happens on the UI thread. It is usually used when a view is created or destroyed. Sometimes, it is also used when the view changes size. LayoutAnimation works only on two properties: opacity and size. Layout Animation is the preferred way to animate as it is high-performant.

Animated API

However, background color cannot be animated using Layout Animation. This is where the Animated API comes in. Animated API allows the use of 4 built-in animatable components:

  1. Animated.View
  2. Animated.Image
  3. Animated.Text
  4. Animated.ScrollView

To animate the opacity of the view, Animated.View is created as follows:

<Animated.View style={[styles.container, { opacity: this.state.opacity }]}>
</Animated.View>

The opacity state is of Animated.Value type.

state = {
    opacity: new Animated.Value(0.7)
}

For doing the animation, the state is not updated using setState. Instead, the Animated API is used as follows.

animate() {
    Animated.sequence([
        Animated.timing(this.state.opacity, {
            delay: 1500,
            duration: 1000,
            toValue: 0.7
        }),
        Animated.timing(this.state.opacity, {
            delay: 500,
            duration: 500,
            toValue: 1.0
        })
    ]).start();
}

A sequence of two animations are run one after another. The first animation is delayed by 1.5 seconds and runs for a second. The second animation is delayed by 500 milli-seconds and runs for half a second.

Animate color

The Animated API does not have built-in support for animating a button. To animate a button, a new wrapper component should be created.

const AnimatedButton = Animated.createAnimatedComponent(TouchableOpacity);

An example usage of Animated Button is shown below:

 <AnimatedButton
    style={[styles.container, { backgroundColor }]}
    onPress={this.handleAnswerPress.bind(this)}
    <Text style={styles.text}>
        {text}
    </Text>
</AnimatedButton>

As it is shown in the code, the background color is animated. There is still a technical problem to overcome. It is possible to set numbers to Animated.Value but not colors.

Animated.sequence([
    Animated.timing(this.state.backgroundColor, {
        delay: 500,
        duration: 500,
        toValue: 1
    }),
    Animated.timing(this.state.backgroundColor, {
        delay: 1500,
        duration: 500,
        toValue: 0
    })
]).start();

The animation changes the background color from 0 to 1 and back to 0. We know that colors do not range from 0 to 1. So, how do we translate the Animated.Value from a number to color. The interpolate method does the job.

const backgroundColor = this.state.backgroundColor.interpolate({
    inputRange: [0, 1],
    outputRange: ['rgba(89, 77, 70, 1)', 'rgba(63, 104, 28, 1)']
});

The interpolation happens on every render. It is the interpolated background color that is set for the AnimatedButton component that we saw earlier.

Related Posts

2 thoughts on “How do I animate the background color of a button in React Native?

  1. All of the above code will work if we create Animated.Value on this (component object). Storing Animated.Value on state is only done for the sake of familiarity. In the above example, this.backgroundColor = new Animated.Value(0) should work. Using this.backgroundColor instead of this.state.backgroundColor is totally fine.

  2. Thank you!! 🙏🏼
    I was struggling to figure out how to make a blinking animation effect in react native and this article saved me!

Leave a Reply

Your email address will not be published.