Andrew Est
Andrew Est

Reputation: 31

How to animate header to show based on scrolling in react native?

So Ideally, When i scroll down, I want the header to disappear(slide down) and when I scroll up I want it to show (slide up). Idc where im at in the page. I just want the animation to fire when those 2 events occur. I see some apps have this but I can't think of how to replicate it. please help me set a basis for this

Upvotes: 1

Views: 12241

Answers (2)

Leonardo Lima
Leonardo Lima

Reputation: 496

You can use Animated from 'react-native'

here an example changing the Topbar height:

import { Animated } from 'react-native';

define maxHeight and minHeight topbar

const HEADER_MAX_HEIGHT = 120;
const HEADER_MIN_HEIGHT = 48;

initialize a variable with the scrollY value

constructor(props) {
   super(props);

   this.state = {
       scrollY: new Animated.Value(
          Platform.OS === 'ios' ? -HEADER_MAX_HEIGHT : 0,
       ),
   };
}

on render you can interpolate a value acording the scrollY Value

render() {
   const { scrollY } = this.state;

   // this will set a height for topbar
   const headerHeight = scrollY.interpolate({
      inputRange: [0, HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT],
      outputRange: [HEADER_MAX_HEIGHT, HEADER_MIN_HEIGHT],
      extrapolate: 'clamp',
   });

   // obs: the inputRange is the scrollY value, (starts on 0) 
   //  and can go until (HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT)
   //  outputRange is the height that will set on topbar

   // obs: you must add a onScroll function on a scrollView like below:

   return (
       <View>
          <Animated.View style={{
             position: 'absolute',
             top: 0,
             left: 0,
             right: 0,
             backgroundColor: '#2e4265',
             height: headerHeight,
             zIndex: 1,
             flexDirection: 'row',
             justifyContent: 'flex-start',
           }}>
             <Text>{title}</Text>
         </Animated.View>
         <ScrollView
            style={{ flex: 1 }}
            scrollEventThrottle={16}
            onScroll={Animated.event(
               [{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }],
          )}>
            <View style={{ height: 1000 }} />
         </ScrollView>
       </View>
   );
}

Upvotes: 0

chin8628
chin8628

Reputation: 476

You can use Animated.FlatList or Animated.ScrollView to make the scroll view, and attach a callback to listen onScroll event when it is changed. Then, using interpolation to map value between y-axis and opacity.

searchBarOpacityAnim is a component's state. By using Animated.event, the state will be updated when a callback is called. Also, don't forget to set useNativeDriver to be true. I've attached the link to document below about why you have to set it.

<Animated.FlatList
  ...
  onScroll={Animated.event(
    [{ nativeEvent: { contentOffset: { y: searchBarOpacityAnim } } }],
    { useNativeDriver: true },
  )}
  ...
/>

Then, use Animated.View wraps your component which you want to animate it. Use .interpolate to map value between the state and component's opacity like the example below...

<Animated.View
  style={{
    opacity: searchBarOpacityAnim.interpolate({
      inputRange: [213, 215],
      outputRange: [0, 1],
    }),
  }}
>
  <SearchBar />
</Animated.View>

You can read more information about useNativeDriver, .interpolate, and Animated.event here.

https://facebook.github.io/react-native/docs/animated#using-the-native-driver

https://facebook.github.io/react-native/docs/animations#interpolation

https://facebook.github.io/react-native/docs/animated#handling-gestures-and-other-events

Upvotes: 4

Related Questions