javascriptreactjsreact-nativescrollviewreact-animations

react-native: How to add header animation in ScrollView onScroll


I am implementing animated header with ScrollView on screen. on scrollView onScroll I am also setting myview on base of scrollview Y position. Like this

const onScroll = ({ nativeEvent: { contentOffset: { y, x } } }) => {
    let _currentSection;
    // loop sections to calculate which section scrollview is on
    state.sections.forEach((section, index) => {
      // adding 15 to calculate Text's height
      const moveToPOsition = wp('24') * 5.8 * index

      console.log((y), state[section], index, moveToPOsition)
      if ((y + 15) > moveToPOsition) _currentSection = index
    })
    // settint the currentSection to the calculated current section
    setState((currentState) => ({ ...currentState, currentSection: _currentSection }))
}

Now on implementing animated header I need to add animation code onScroll. This one

const handleScroll = Animated.event(
    [
      {
        nativeEvent: {
          contentOffset: { y: scrollY.current },
        },
      },
    ],
    {
      useNativeDriver: true,
    },
  );

When I add both codes togather and called onScoll of scrollview they does not work ... while separately they work.

const onScroll = ({ nativeEvent: { contentOffset: { y, x } } }) => {
    let _currentSection;
    // loop sections to calculate which section scrollview is on
    state.sections.forEach((section, index) => {
      // adding 15 to calculate Text's height
      const moveToPOsition = wp('24') * 5.8 * index

      console.log((y), state[section], index, moveToPOsition)
      if ((y + 15) > moveToPOsition) _currentSection = index
    })
    // settint the currentSection to the calculated current section
    setState((currentState) => ({ ...currentState, currentSection: _currentSection }))


    Animated.event(
      [
        {
          nativeEvent: {
            contentOffset: { y: scrollY.current },
          },
        },
      ],
      {
        useNativeDriver: true,
      },
    )

  }

Calling onScoll like this

<Animated.ScrollView
   style={styles.scrollView}
   ref={scrollView}
   contentContainerStyle={{paddingTop: headerHeight}}
   scrollEventThrottle={100}
   bounces={false}
   onScroll={onScroll}>
   {state.sections.map(section => (
      <Item key={section.id} category={section}
            onItemLayout={onItemLayout} data={data} />
   ))}
</Animated.ScrollView>

Solution

  • I found a solution

    const onScroll = ({ nativeEvent: { contentOffset: { y, x } } }) => {
        let _currentSection;
        // loop sections to calculate which section scrollview is on
        state.sections.forEach((section, index) => {
          // adding 15 to calculate Text's height
          const moveToPosition = wp('24') * 5.8 * index
          // console.log((y), state[section], index, moveToPOsition)
          if ((y + 15) > moveToPosition) _currentSection = index
        })
    
        const moveTabToPosition = ((Screen.width) / 5) * _currentSection
        tabScrollView.current?.scrollTo({ x: moveTabToPosition, y: 0, animated: true });
        if (state.currentSection != _currentSection) {
          // settint the currentSection to the calculated current section
          setState((currentState) => ({ ...currentState, currentSection: _currentSection }))
        }
      }
    

    and add it in Animated.Event link this

    const handleScroll = Animated.event(
        [
          {
            nativeEvent: {
              contentOffset: { y: scrollY.current },
            },
          },
        ],
        {
          useNativeDriver: true,
          listener: event => {
            onScroll(event);
          },
        },
      );