3

I want to add a collapsable header in my Application. I created a separated component for the Header view.

interface Props{
    userData: UserDetails | null
    scrollY: Animated.Value
}
    
const HEADER_EXPANDED_HEIGHT = sizeProportionHeight(320)
const HEADER_COLLAPSED_HEIGHT = sizeProportionHeight(142)

const CollapsableHeader : React.FC<Props> = ({userData, scrollY}) => {
    
   const headerHeight = scrollY.interpolate({
        inputRange: [0, HEADER_EXPANDED_HEIGHT-HEADER_COLLAPSED_HEIGHT],
        outputRange: [HEADER_EXPANDED_HEIGHT, HEADER_COLLAPSED_HEIGHT],
        extrapolate: 'clamp'
    })

    return(
        <Animated.View style={{height: headerHeight, width: SCREEN_WIDTH, position:'absolute', top:0, left: 0}}/>
    )
}

export default CollapsableHeader

I my main page I added the header as such:

interface Props{
    navigation: StackNavigationProp<MainParamList,'HomeScreen'>
    route: RouteProp<MainParamList,'HomeScreen'>
}

interface HeaderState {
    scrollY: Animated.Value   
}

interface HomeScreenState {
    header: HeaderState
}

const HomeScreen : React.FC<Props> = ({ navigation, route }) => {

    const [state, setState] = React.useState<HomeScreenState>({header: {scrollY: new Animated.Value(0)}})

    return (
        <View  style={styles.container}>
            <CollapsableHeader userData={null} 
                               scrollY={state.header.scrollY}/>
            <ScrollView contentContainerStyle={[styles.scrollContainer]}
                        onScroll={Animated.event(
                            [{
                                nativeEvent: {
                                    contentOffset: {
                                        y: state.header.scrollY
                                    }
                                    
                                },
                            }],
                            {
                                useNativeDriver:true
                            }
                            
                        )}
                        scrollEventThrottle={16}>
/// Scrollable content
                </ScrollView>
            </View>
        )
    }

However if I try to scroll I get an error stating

this.props.onScroll is not a function. (In 'this.props.onScroll(e)', 'this.props.onScroll' is an instance of AnimatedEvent)

If I remove the useNativeDriver: true the error disappears, but instead I get a warning saying that I'm missing useNativeDriver.

How can I correctly use this collapsable animation?

Keselme
  • 3,779
  • 7
  • 36
  • 68

1 Answers1

4

Using nativeDriver means we can send everything about the animation to native before it has even started and allows native code to perform the animation on the UI thread without having to go through the bridge on every frame.

Not everything you can do with Animated is currently supported in Native Animated. The main limitation is that you can only animate non-layout properties, things like transform and opacity will work but Flexbox and position properties won't.

So as you can see width and height aren't supported by nativeDriver, you can just disable it.

useNativeDriver: false

No need to completely remove it.

Note: Change ScrollView to Animated.ScrollView too:

Leri Gogsadze
  • 2,958
  • 2
  • 15
  • 24