Skip to content

Instantly share code, notes, and snippets.

@anastely
Last active September 8, 2021 16:21
Show Gist options
  • Save anastely/e6dde4379ec6ec62698d1407f06487fa to your computer and use it in GitHub Desktop.
Save anastely/e6dde4379ec6ec62698d1407f06487fa to your computer and use it in GitHub Desktop.
import React, { useEffect, useRef, useState } from "react";
import {
Dimensions,
FlatList,
I18nManager,
StyleSheet,
Text,
TouchableOpacity,
View,
} from "react-native";
const { width } = Dimensions.get("window");
const headers = [
"header1",
"header header 2",
"header3",
"header header4",
"header5",
"header header6",
"header7",
"header header8",
"header9",
"header10",
];
const content = [...Array(10).keys()].fill(0);
const TAB_WIDTH = 150;
const HeaderTabView = () => {
const [activeIndex, setActiveIndex] = useState(0);
const headerRef = useRef();
const contentRef = useRef();
const scrollToActiveIndex = (index) => {
// current active page (index)
setActiveIndex(index);
// scroll the content when press tab
contentRef.current.scrollToOffset({
offset: index * width,
animated: true,
});
// if the tab width is greater than half(middle) of the screen, scroll to the middle of the screen otherwise set offset 0
if (index * TAB_WIDTH - TAB_WIDTH / 2 > width / 2) {
headerRef.current.scrollToOffset({
offset: index * TAB_WIDTH - width / 2 + TAB_WIDTH / 2,
animated: true,
});
} else {
headerRef.current.scrollToOffset({
offset: 0,
animated: true,
});
}
};
return (
<View style={styles.container}>
<FlatList
data={headers}
style={{
flexGrow: 0,
flexDirection: I18nManager.isRTL ? "row-reverse" : "row",
}}
ref={headerRef}
contentContainerStyle={{
flexGrow: 1,
}}
keyExtractor={(item, index) => index.toString()}
horizontal
showsHorizontalScrollIndicator={false}
renderItem={({ item, index }) => (
<View style={{ width: TAB_WIDTH }}>
<TouchableOpacity
onPress={() => scrollToActiveIndex(index)}
key={item}
style={[
styles.headerItem,
{
backgroundColor: activeIndex == index ? "#b6d7fc" : "#82bcff",
},
]}>
<Text>{item}</Text>
</TouchableOpacity>
{activeIndex == index && <View style={styles.headerBar} />}
</View>
)}
/>
<FlatList
data={content}
ref={contentRef}
keyExtractor={(item, index) => index.toString()}
horizontal
pagingEnabled
onMomentumScrollEnd={(ev) => {
scrollToActiveIndex(
Math.floor(ev.nativeEvent.contentOffset.x / width),
);
}}
decelerationRate="fast"
renderItem={({ item, index }) => (
<View key={item} style={styles.mainItem}>
<Text>Animation happens once scrolling ended</Text>
<Text>card {index + 1}</Text>
</View>
)}
/>
</View>
);
};
export default HeaderTabView;
const styles = StyleSheet.create({
container: {
flex: 1,
},
headerScroll: {
flexGrow: 0,
},
headerItem: {
alignItems: "center",
justifyContent: "center",
padding: 20,
},
mainItem: {
width: width,
borderWidth: 5,
borderColor: "#fff",
backgroundColor: "#ccc",
alignItems: "center",
justifyContent: "space-evenly",
},
headerBar: {
height: 2,
width: "90%",
alignSelf: "center",
backgroundColor: "#000",
position: "absolute",
bottom: 0,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment