PedroBern / react-native-collapsible-tab-view

A cross-platform Collapsible Tab View component for React Native
MIT License
875 stars 171 forks source link

How to trigger an event when header is hidden or trigger an event when scroll down? #150

Closed sankar9659 closed 3 years ago

sankar9659 commented 3 years ago

image image

How to trigger an event, when scroll down (when the header is hidden). I m using this package for sticky header. I want to move the header text in top of the screen. when scroll down (when header is hidden, i need to show the header in top of the screen) like above screenshot. Here the lorum ipsum shown in header (1st screenshot), when i starts to scroll, i need to show the header in top of the screen) like second image. How can i implement this, any possible?

"react": "17.0.1", "react-native": "0.63.3", "react-native-collapsible-tab-view": "^2.0.2",

My code is, import React from 'react'; import { StyleSheet, View, Text, Animated } from 'react-native'; import { CollapsibleTabView, useCollapsibleScene, } from 'react-native-collapsible-tab-view';

const SomeRoute = ({ routeKey, color, }) => { const scrollPropsAndRef = useCollapsibleScene(routeKey);

return (
    <Animated.ScrollView
        style={{ backgroundColor: color }}
        {...scrollPropsAndRef}
    >
        <Text style={{ padding: 20, color: "black" }}> Lorem Ipsum is simply</Text>
    </Animated.ScrollView>
);

};

const renderHeader = () => (

Lorem Ipsum is Header

);

const renderScene = ({ route, jumpTo }) => { switch (route.key) { case 'first': return ; case 'second': return ; } };

const App = () => { const [index, setIndex] = React.useState(0); const [routes] = React.useState([ { key: 'first', title: 'First' }, { key: 'second', title: 'Second' }, ]);

const handleIndexChange = (index) => {
    setIndex(index);
};

return (
    <View style={{ flex: 1 }}>
        <Text>Sample Text</Text>
        <CollapsibleTabView
            navigationState={{ index, routes }}
            renderScene={renderScene}
            onIndexChange={handleIndexChange}
            renderHeader={renderHeader} // optional
            disableSnap={false}
        />
    </View>
);

};

export default App;

const styles = StyleSheet.create({ header: { backgroundColor: '#2196f3', justifyContent: 'center', alignItems: 'center', elevation: 4, }, headerText: { color: 'white', fontSize: 24, }, content: { height: 1500, }, });

Thanks in advance.

PedroBern commented 3 years ago

Hi @sankar9659 you can pass an animatedValue to the CollapsibleTabView and listen to changes on it.

const [animatedValue] = React.useState(new Animated.Value(0))

React.useEffect(() => {
    const listener = animatedValue.addListener(({ value }) => {
        ....
    })

    return () => { animatedValue.removeListener(listener) }
}, []}

<CollapsibleTabView
    ...
    animatedValue={animatedValue}
/>
sankar9659 commented 3 years ago

Thanks @PedroBern, Its working now,

abelmenkveld commented 3 years ago

Hi @PedroBern, is there also an approach to accomplish this in v4? The navigation bar I try to animate is located outside of Tabs.Container

andreialecu commented 3 years ago

@abelmenkveld the top value from the useHeaderMeasurements() hook in v4 is a reanimated2 SharedValue. You could use useAnimatedReaction, useDerivedValue or useAnimatedStyle on it to react to changes. See:

https://docs.swmansion.com/react-native-reanimated/docs/next/api/useAnimatedReaction/

PedroBern commented 3 years ago

@abelmenkveld in addition to @andreialecu 's answer, you can create your animation logic inside the header component (to get the context with useHeaderMeasurements()) and save it to your own context

// in the header component
const { top, height } useHeaderMeasurements()
const style = useAnimatedStyle(...)
saveStyleToMyOwnContext(style) // inside useEffect

// in the navigation bar you want to animate
const { style } = useMyOwnContext()
abelmenkveld commented 3 years ago

Thanks a lot guys for your great help! Finally got it working with useAnimatedReaction :). One last question: Is there a way to retrieve the contentOffset.y value of a ScrollView/FlatList? I can also create a new issue if this is simply a feature request, since we might need a dedicated hook for this?

In my use case I have a floating "scroll to today" button in a calendar-like list which should hide/show based on the scroll position

andreialecu commented 3 years ago

A hook to expose the current Y would be useful indeed.

Would you like to open a PR for it? It shouldn't be a big change. Take a look at one of the other hooks for pointers.