Search code examples
react-nativecollapsable

How to hide Header and Footer at the same time with the Animated API in React Native


I just wonder how can I hide both Header and Footer at the same time and with the same animated value?

Becouse I think I cannot use the same animated value for the animate multiple components at the same time.

MY COMPONENT

<SafeAreaView style={{ flex: 1 }}>
            <Animated.View
                style={{
                    transform: [{ translateY }],
                    position: "absolute",
                    top: 0,
                    left: 0,
                    zIndex: 100,
                    width: "100%",
                }}
            >
                <MainHeader logo="socialLogo" navigation={navigation} />
            </Animated.View>
            <Animated.FlatList
                ref={ref}
                onEndReachedThreshold={0.5}
                contentContainerStyle={{ paddingTop: HEADER_HEIGHT }}
                bounces={false}
                onScroll={handleScroll}
                nestedScrollEnabled={true}
                ListHeaderComponent={<Stories data={data} app={app} />}
                pinchGestureEnabled={false}
                ListEmptyComponent={<FeedItemLazy />}
                onMomentumScrollEnd={handleSnap}
                scrollEventThrottle={16}
                renderScrollComponent={(props) => <ScrollView {...props} />}
                showsVerticalScrollIndicator={false}
                maxToRenderPerBatch={10}
                onEndReached={() => {
                    props.social.getFeeds.executeNext({ lastID: lastId });
                }}
                refreshControl={
                    <RefreshControl
                        refreshing={isRefreshing}
                        onRefresh={handleRefresh}
                    />
                }
                data={data}
                renderItem={({ item, index }) => (
                    <>
                        <FeedItem
                            data={item}
                            app={app}
                            navigation={navigation}
                            social={social}
                        />
                        <Separator height={2} />
                    </>
                )}
                keyExtractor={(item) => item._id}
            />
            {social.getFeeds.isExecuting && (
                <LottieView
                    source={require("../../../../assets/animation/16337-banana-loader.json")}
                    loop
                    autoPlay
                    style={{ width: 50, height: 50 }}
                />
            )}
            <ModalSelector navigation={navigation} />
        </SafeAreaView>

This is a Feeds component. Users feeds being listed in the Flatlist, and my goal is when user scrolls down make the MainHeader and Bottom tabs collapsable. I think hardest part is to make bottom tabs unvisible, becose they are coming directly from react-navigation v5. from createBottomTabNavigator. I dont know how can I transfer the translateY value to tab navigator.


Solution

  • import React from 'react';
    import {
      Animated,
      Easing,
      Button,
      View,
      StyleSheet,
      Text,
      TouchableOpacity,
    } from 'react-native';
    
    const App = () => {
      const animatedValue = React.useRef(new Animated.Value(0)).current;
      const [hidden, setHidden] = React.useState(false);
    
      const startAnimation = (toValue) => {
        Animated.timing(animatedValue, {
          toValue: hidden ? 0 : 1,
          duration: 700,
          easing: Easing.linear,
          useNativeDriver: true,
        }).start(() => setHidden(!hidden));
      };
    
      const translateY = animatedValue.interpolate({
        inputRange: [0, 1],
        outputRange: [0, -50],
        extrapolate: 'clamp',
      });
    
      return (
        <View style={{ flex: 1 }}>
          <Animated.View
            style={[styles.item, { top: 0, transform: [{ translateY }] }]}
          />
          <TouchableOpacity
            style={styles.button}
            onPress={startAnimation.bind(null, 1 - animatedValue.__value)}>
            <Text>Hide</Text>
          </TouchableOpacity>
          <Animated.View
            style={[
              styles.item,
              {
                bottom: 0,
                transform: [{ translateY: Animated.multiply(translateY, -1) }],
              },
            ]}
          />
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      item: {
        width: '100%',
        height: 50,
        position: 'absolute',
        backgroundColor: 'red',
      },
      button: {
        width: '50%',
        height: 50,
        backgroundColor: 'pink',
        justifyContent: 'center',
        alignItems: 'center',
        alignSelf: 'center',
        borderRadius: 25,
        position: 'absolute',
        top: 200,
      },
    });
    
    export default App;
    

    Live Demo.