-
-
Save EQuimper/dd5a4d6bae369c5dce0898cde926b340 to your computer and use it in GitHub Desktop.
Revisions
-
EQuimper renamed this gist
Jun 19, 2020 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
maitham revised this gist
Jun 6, 2020 . 1 changed file with 10 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,7 +4,7 @@ import { TabView } from 'react-native-tab-view'; import { TabScreen } from './Tab'; import { CustomTabBar } from './TabBar'; import { ThemeContext } from 'react-native-elements'; import { useHeaderHeight } from '@react-navigation/stack'; const AnimatedHeader = ({ style, content }) => { return <Animated.View style={style}>{content}</Animated.View>; }; @@ -17,6 +17,8 @@ const initialLayout = { const HEADER_HEIGHT = 320; const TABBAR_HEIGHT = 48; const TOTAL_HEADER_HEIGHT = HEADER_HEIGHT + TABBAR_HEIGHT; export const Tab: React.FC = ({ routeDefinitions, header, dataMap }) => { const { theme: { colors }, @@ -30,6 +32,7 @@ export const Tab: React.FC = ({ routeDefinitions, header, dataMap }) => { extrapolate: 'clamp', }), ).current; const navHeaderHeight = useHeaderHeight(); // react-native-tab-view const [index, setIndex] = useState(0); @@ -78,15 +81,18 @@ export const Tab: React.FC = ({ routeDefinitions, header, dataMap }) => { }; const renderScene = ({ route }) => { const contentInset = Math.max( initialLayout.height - dataMap[route.key].length * 75 - TABBAR_HEIGHT - navHeaderHeight, 0, ); return ( <TabScreen ref={(ref) => getFlatListRefs(ref, route)} data={dataMap[route.key]} itemType={route.key} contentInset={contentInset === 0 ? 0 : contentInset} scrollContentContainerStyle={{ paddingTop: TOTAL_HEADER_HEIGHT, }} onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], { useNativeDriver: true, @@ -152,8 +158,6 @@ export const Tab: React.FC = ({ routeDefinitions, header, dataMap }) => { }; export const TabScreen: React.FC<TabProps> = React.memo( React.forwardRef( ( -
maitham revised this gist
Jun 6, 2020 . 1 changed file with 42 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -150,3 +150,45 @@ export const Tab: React.FC = ({ routeDefinitions, header, dataMap }) => { </> ); }; export const TabScreen: React.FC<TabProps> = React.memo( React.forwardRef( ( { scrollContentContainerStyle, onScroll, onScrollEndDrag, onMomentumScrollEnd, data, itemType, contentInset, }, ref, ) => { return ( <AnimatedFlatList ref={ref} data={data} renderItem={({ item }) => <Item item={item} itemType={itemType} />} keyExtractor={keyExtractor} scrollEventThrottle={1} contentInset={{ bottom: contentInset }} onScroll={onScroll} showsVerticalScrollIndicator={false} onScrollEndDrag={onScrollEndDrag} onMomentumScrollEnd={onMomentumScrollEnd} contentContainerStyle={[{}, scrollContentContainerStyle]} /> ); }, ), ); function keyExtractor(item: any, index: number): string { return index.toString(); } -
maitham created this gist
Jun 6, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,152 @@ import React, { useState, useRef, useContext, useCallback } from 'react'; import { Dimensions, View, Animated } from 'react-native'; import { TabView } from 'react-native-tab-view'; import { TabScreen } from './Tab'; import { CustomTabBar } from './TabBar'; import { ThemeContext } from 'react-native-elements'; const AnimatedHeader = ({ style, content }) => { return <Animated.View style={style}>{content}</Animated.View>; }; const initialLayout = { width: Dimensions.get('window').width, height: Dimensions.get('window').height, }; const HEADER_HEIGHT = 320; const TABBAR_HEIGHT = 48; export const Tab: React.FC = ({ routeDefinitions, header, dataMap }) => { const { theme: { colors }, } = useContext(ThemeContext); const tabRef = useRef(null); const scrollY = useRef(new Animated.Value(0)).current; const headerTranslateY = useRef( scrollY.interpolate({ inputRange: [0, HEADER_HEIGHT], outputRange: [0, -HEADER_HEIGHT], extrapolate: 'clamp', }), ).current; // react-native-tab-view const [index, setIndex] = useState(0); const routes = routeDefinitions; const listRefs = useRef([]); const listRefsOffsets = useRef({}); const getFlatListRefs = (ref, route) => { if (ref) { const found = listRefs.current.find((e) => e.key === route.key); if (!found) { listRefs.current.push({ key: route.key, value: ref, }); } } }; const scrollTabToOffset = (item, y) => { item.value.scrollToOffset({ offset: y, animated: false, }); }; const syncHiddenTab = (hiddenTab, currentTabOffsets) => { const offsets = listRefsOffsets.current[hiddenTab.key]; if (!offsets?.offset && currentTabOffsets.offset > HEADER_HEIGHT) { scrollTabToOffset(hiddenTab, HEADER_HEIGHT); } else if (currentTabOffsets.offset >= HEADER_HEIGHT) { scrollTabToOffset(hiddenTab, HEADER_HEIGHT); } else if (currentTabOffsets.offset < HEADER_HEIGHT) { scrollTabToOffset(hiddenTab, currentTabOffsets.offset); } }; const syncOffset = () => { const curRouteKey = routes[index].key; const currentTabOffsets = listRefsOffsets.current[curRouteKey]; listRefs.current.forEach((item) => { if (item.key !== curRouteKey) { syncHiddenTab(item, currentTabOffsets); } }); }; const renderScene = ({ route }) => { const contentInset = Math.max(initialLayout.height - dataMap[route.key].length * 65, 0); return ( <TabScreen ref={(ref) => getFlatListRefs(ref, route)} data={dataMap[route.key]} itemType={route.key} contentInset={contentInset === 0 ? 0 : 240} scrollContentContainerStyle={{ paddingTop: HEADER_HEIGHT + TABBAR_HEIGHT, }} onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], { useNativeDriver: true, listener: (event) => { listRefsOffsets.current[route.key] = { offset: event.nativeEvent.contentOffset.y }; }, })} onScrollEndDrag={() => syncOffset()} onMomentumScrollEnd={() => syncOffset()} /> ); }; const AnimatedTabBar = (props) => ( <Animated.View style={{ position: 'absolute', top: HEADER_HEIGHT, left: 0, right: 0, zIndex: 1, paddingLeft: 8, paddingBottom: 10, transform: [{ translateY: headerTranslateY }], backgroundColor: colors.background, }} > <CustomTabBar tabBarStyle={{ marginTop: 10 }} currentIndex={index} onIndexChange={setIndex} navigationState={props.navigationState} ref={tabRef} /> </Animated.View> ); return ( <> <AnimatedHeader style={{ position: 'absolute', height: HEADER_HEIGHT, transform: [{ translateY: headerTranslateY }], zIndex: 1, backgroundColor: colors.background, }} content={header} /> <View style={{ flex: 1 }}> <TabView navigationState={{ index, routes }} renderScene={renderScene} renderTabBar={(props) => <AnimatedTabBar {...props} />} initialLayout={initialLayout} onIndexChange={setIndex} style={{ overflow: 'visible' }} /> </View> </> ); };