ReactNative: animate backgroundColor according to ScrollView scroll position

Viewed 379

I have a ScrollView and I want to have a View with background color white, then if scroll position is more than 0 change it to transparent, and back to white if scroll goes back to 0.

I tried to get started but react native animations seem crazy complicated coming back from a vue.js background.

Here is my code:

const [animation, setAnimation] = useState(new Animated.Value(0))

const handleScroll = (event) => {
        console.log(event.nativeEvent.contentOffset.y);
        var scroll = event.nativeEvent.contentOffset.y;
        if(scroll > 0)
        {
            handleAnimation();
        }
      };

      const boxInterpolation =  animation.interpolate({
        inputRange: [0, 1],
        outputRange:["rgb(255,255,255)" , "rgba(255,255,255,0)"]
      })
    const animatedStyle = {
        backgroundColor: boxInterpolation
      }


      const handleAnimation = () => {
        Animated.timing(animation, {
          toValue:1,
          duration: 1000,
          useNativeDriver: true
        }).start(); 
      };

And my views

<ScrollView showsVerticalScrollIndicator={false} scrollEventThrottle={16} onScroll={handleScroll} style={{flex:1,backgroundColor:'white',position:'relative'}}>
            <View style={{ width:'100%', height:505,position:'relative' ,backgroundColor:'red}}>
            </View>
            
            </ScrollView>
            <Animated.View style={{width:'100%',height:100,...animatedStyle, flexDirection:'row',justifyContent:'space-around',alignItems:'center',position:'absolute',bottom:0,left:0}}>
            </Animated.View>
1 Answers

The recommend way of getting the ScrollView x and y position is this below

const scrolling = React.useRef(new Animated.Value(0)).current;

<Animated.ScrollView 
     onScroll={Animated.event(
      [{
        nativeEvent: {
          contentOffset: {
            y: scrolling,
          },
        },
      }],
      { useNativeDriver: false },
    )}
</Animated.View>

Now everything works heres a full example (https://snack.expo.dev/@heytony01/ca5000) must be run a phone not web. And below is the code.

import  React from 'react';
import { Button,View,Animated,ScrollView } from 'react-native';

export default function App() {

  const scrolling = React.useRef(new Animated.Value(0)).current;
  const boxInterpolation =  scrolling.interpolate({
    inputRange: [0, 100],
    outputRange:["rgb(255,255,255)" , "rgba(255,255,255,0)"],
  })
  const animatedStyle = {
    backgroundColor: boxInterpolation
  }

  return (
    <View style={{flex:1}}>
     <Animated.ScrollView showsVerticalScrollIndicator={false} scrollEventThrottle={16}  style={{flex:1,backgroundColor:'black',position:'relative'}}
     onScroll={Animated.event(
      [{
        nativeEvent: {
          contentOffset: {
            // 
            y: scrolling,
          },
        },
      }],
      { useNativeDriver: false },
    )}
     >
            <View style={{ width:'100%', height:505,position:'relative', backgroundColor:'red'}}>
            </View>
            
      </Animated.ScrollView>
      <Animated.View style={{width:'100%',height:100,...animatedStyle, flexDirection:'row',justifyContent:'space-around',alignItems:'center',position:'absolute',bottom:0,left:0,zIndex:1}}>
      
      </Animated.View>

    </View>
  );
}

Also if you want to print the animated values when debugging you can do this

React.useEffect(()=>{

  scrolling.addListener(dic=>console.log(dic.value))

  return ()=> scrolling.removeAllListeners()
},[])
Related