Skip to content

Instantly share code, notes, and snippets.

@andigu
Last active March 5, 2024 00:27
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save andigu/53edb75a2354cc52655e3940225e0d0f to your computer and use it in GitHub Desktop.
Save andigu/53edb75a2354cc52655e3940225e0d0f to your computer and use it in GitHub Desktop.
import React, {Component} from "react";
import {Animated, Dimensions, Platform, Text, View} from 'react-native';
import {Body, Header, List, ListItem as Item, ScrollableTab, Tab, Tabs, Title} from "native-base";
const NAVBAR_HEIGHT = 56;
const {width: SCREEN_WIDTH} = Dimensions.get("window");
const COLOR = "rgb(45,181,102)";
const TAB_PROPS = {
tabStyle: {width: SCREEN_WIDTH / 2, backgroundColor: COLOR},
activeTabStyle: {width: SCREEN_WIDTH / 2, backgroundColor: COLOR},
textStyle: {color: "white"},
activeTextStyle: {color: "white"}
};
export class CollapsingNav extends Component {
scroll = new Animated.Value(0);
headerY;
constructor(props) {
super(props);
this.headerY = Animated.multiply(Animated.diffClamp(this.scroll, 0, NAVBAR_HEIGHT), -1);
}
render() {
const tabContent = (
<List>{new Array(20).fill(null).map((_, i) => <Item
key={i}><Text>Item {i}</Text></Item>)}</List>);
const tabY = Animated.add(this.scroll, this.headerY);
return (
<View>
{Platform.OS === "ios" &&
<View style={{backgroundColor: COLOR, height: 20, width: "100%", position: "absolute", zIndex: 2}}/>}
<Animated.View style={{
width: "100%",
position: "absolute",
transform: [{
translateY: this.headerY
}],
elevation: 0,
flex: 1,
zIndex: 1,
backgroundColor: COLOR
}}>
<Header style={{backgroundColor: "transparent"}} hasTabs>
<Body>
<Title>
<Text style={{color: "white"}}>
Collapsing Navbar
</Text>
</Title>
</Body>
</Header>
</Animated.View>
<Animated.ScrollView
scrollEventThrottle={1}
bounces={false}
showsVerticalScrollIndicator={false}
style={{zIndex: 0, height: "100%", elevation: -1}}
contentContainerStyle={{paddingTop: NAVBAR_HEIGHT}}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.scroll}}}],
{useNativeDriver: true},
)}
overScrollMode="never">
<Tabs renderTabBar={(props) => <Animated.View
style={[{
transform: [{translateY: tabY}],
zIndex: 1,
width: "100%",
backgroundColor: COLOR
}, Platform.OS === "ios" ? {paddingTop: 20} : null]}>
<ScrollableTab {...props} underlineStyle={{backgroundColor: "white"}}/>
</Animated.View>
}>
<Tab heading="Tab 1" {...TAB_PROPS}>
{tabContent}
</Tab>
<Tab heading="Tab 2" {...TAB_PROPS}>
{tabContent}
</Tab>
</Tabs>
</Animated.ScrollView>
</View>
);
}
}
@pedrofneves
Copy link

Hi... I'm trying to set the TabBar aligned to the bottom (fixed) but I had no success. Can you help me?

@pat1k2k
Copy link

pat1k2k commented Dec 21, 2018

This is clear, thanks for posting this,

@alz10
Copy link

alz10 commented Apr 18, 2019

Thank you very much for this. <3

@alz10
Copy link

alz10 commented Apr 18, 2019

Hey man, i just notice that if the first Tab has a bigger height compare to other Tabs, its height will be transferred to other tabs that are smaller in height. Its like whoever Tab has the bigger height, its height will be distributed to other tabs height as well.

@kneza23
Copy link

kneza23 commented Dec 19, 2019

Amazing work man, but there is a problem when you have SectionList component, i find it impossible to get the seacton sticky headers to stick with CollapsingNav.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment