title: How can I make an animated Linear Gradient button?
body: <p>I am using React Native, and one of the components we need is a button with a gradient background. OnPress the colors should smoothly animate from their base value to their active value, and when you finish they should smoothly go back to their base value. I'm using a TouchableHighlight component to get access to the onShowUnderlay and onHideUnderlay functions to trigger the gradient change.</p>
  
  <p>I was successfully able to get it to change abruptly on state change, but I'm having a harder time getting it to smoothly animate. When I used the following code, the emulator gives me this error: <code>JSON value '&lt;null&gt;' of type NSNull cannot be converted to a UI Color. Did you forget to call processColor() on the JS side?</code>, which I think is related to LinearGradient not being able to read the interpolated values as an RGBA value.</p>
  
  <p>Am I not using the Animated API or the LinearGradient correctly? Or is it just not possible to do it this way?</p>
  
  <pre><code>import React, { PureComponent } from 'react';
  import { Animated, View, TouchableHighlight, Text } from 'react-native';
  import LinearGradient from 'react-native-linear-gradient';
  import styles from './styles/FooterButton.styles';
  
  const AnimatedGradient = Animated.createAnimatedComponent(LinearGradient);
  
  export default class FooterGradientButton extends PureComponent {
      midColor = new Animated.Value(0);
      lastColor = new Animated.Value(0);
  
    showUnderlay = () =&gt; {
      this.midColor.setValue(0);
      this.lastColor.setValue(0);
      Animated.parallel([
        Animated.timing(this.midColor, {
          duration: 500,
          toValue: 1,
        }),
        Animated.timing(this.lastColor, {
          duration: 500,
          toValue: 1,
        }),
      ]).start();
    };
  
    hideUnderlay = () =&gt; {
      this.midColor.setValue(1);
      this.lastColor.setValue(1);
      Animated.parallel([
        Animated.timing(this.midColor, {
          duration: 500,
          toValue: 0,
        }),
        Animated.timing(this.lastColor, {
          duration: 500,
          toValue: 0,
        }),
      ]).start();
    };
  
    render() {
      const firstColor = 'rgba(52, 85, 219, 1)';
      const midColor = this.midColor.interpolate({
        inputRange: [0, 1],
        outputRange: ['rgba(19, 144, 255, 1)', 'rgba(52,85,219, 1)'],
      });
      const lastColor = this.lastColor.interpolate({
        inputRange: [0, 1],
        outputRange: ['rgba(2,194,211, 1)', 'rgba(30,144,255, 1)'],
      });
  
      return (
        &lt;View style={[styles.margin, styles.shadow]}&gt;
          &lt;AnimatedGradient start={{ x: 0.0, y: 0.5 }} end={{ x: 1, y: 0.5 }} style={{ flex: 1 }} colors={[firstColor, midColor, lastColor]}&gt;
            &lt;TouchableHighlight
              activeOpacity={1}
              underlayColor="#ffffff00"
              onShowUnderlay={() =&gt; this.showUnderlay()}
              onHideUnderlay={() =&gt; this.hideUnderlay()}
              style={[styles.gradientButton, styles.androidButton]}
              onPress={() =&gt; (!this.props.inactive ? this.props.onPress() : null)}
            &gt;
              &lt;Text style={[styles.buttonText, { color: 'white' }]}&gt;NEXT&lt;/Text&gt;
            &lt;/TouchableHighlight&gt;
          &lt;/AnimatedGradient&gt;
        &lt;/View&gt;
      );
    }
  }
  </code></pre>