skip to Main Content

The header appears before the user starts scrolling the list, and the FlatList fills the entire screen as the user starts scrolling the list. The animation must be transitioned in one move. Not while the user keeps scrolling. I don’t know the name of such lists. Instagram and YouTube comments are similar. I prepared visuals to explain better. How can I make this type of list?

enter image description here

2

Answers


  1. Chosen as BEST ANSWER

    I haven't fully developed it yet, but roughly the idea below worked. I shared it in case it might be useful to someone.

    import React, { useRef } from "react";
    import { SafeAreaView, View, Text, Animated, FlatList } from "react-native";
    
    const DATA = [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }];
    
    function itemComponent({ item }) {
        return (
            <View style={{ justifyContent: "center", alignItems: "center", backgroundColor: "yellow", margin: 64 }}>
                <Text style={{ color: "black", fontSize: 32 }}>{item.id}</Text>
            </View>
        )
    }
    
    function App() {
    
        const scrollY = useRef(new Animated.Value(0)).current;
        const animationValue = useRef(new Animated.Value(0)).current;
    
        function animation(toValue) {
            Animated.timing(animationValue, {
                toValue: toValue,
                duration: 200,
                useNativeDriver: true,
            }).start();
        }
    
        function onMomentumScrollBegin() {
            if (scrollY._value > 0) {
                animation(1)
            }
        }
    
        function onMomentumScrollEnd() {
            if (scrollY._value <= 0) {
                animation(0)
            }
        }
    
        return (
            <SafeAreaView>
    
                <Animated.View style={{
                    backgroundColor: "red",
                    transform: [{ translateY: animationValue.interpolate({ inputRange: [0, 1], outputRange: [200, 0], extrapolate: "clamp" }) }]
                }}>
    
                    <FlatList
                        data={DATA}
                        renderItem={itemComponent}
                        keyExtractor={item => item.id}
                        onScroll={
                            Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], { useNativeDriver: false })
                        }
                        onMomentumScrollBegin={onMomentumScrollBegin}
                        onMomentumScrollEnd={onMomentumScrollEnd}
                    />
    
                </Animated.View>
    
            </SafeAreaView>
        );
    }
    
    export default App;
    

  2. I use an Animated.View for that. I have 2 headers, the first one inside ListHeaderComponent FlatList param and this animated one hidden. When user scrolls down the ListHeaderComponent hide and when user scrolls up i show the animated one.

    Here you have the Animated.view:

       <Animated.View>
        {!fullSearcher && (
          <View>
            //whatever you want inside header
          </View>
        )}
      </Animated.View>
    

    And here you have the code to manage this animated view:

     const [fullSearcher, setFullSearcher] = useState(true);
     const handleScroll = (event: any) => {
       const windowHeight = Dimensions.get('window').height;
       const scrollHeight: number = event.nativeEvent.contentOffset.y;
       if (scrollHeight <= 400 && !fullSearcher) {
        setFullSearcher(true);
       } else if (scrollHeight > windowHeight && fullSearcher) {
        setFullSearcher(false);
       }
     };
    

    And then this inside FlatList onScroll param:

    onScroll={Animated.event(
      [{nativeEvent: {contentOffset: {y: scrollOffsetY}}}],
      {
        useNativeDriver: false,
        listener: event => handleScroll(event),
      },
    )}
    

    Hope this helps!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search