I am using react-navigation Tab Navigation. I have a header above my tab navigation and it can collapse and expand corresponding to the scrollView.
This is my problem: When I scroll all the way up, the header will collapse and thats what I want but the tabBar will stay static(Please see the photo). Is there a way I could set the tabBar margin corresponding to the scrollview? So that there is no marginTop when the header is collapsed.

const Header_Maximum_Height = 40;
const Header_Minimum_Height = 0;
export default class App extends Component {
render(){
return (
<View style={{flex:1, marginTop:30}}>
<AppContainer/>
</View>
)
}
}
class HomeScreen extends Component{
constructor()
{
super();
this.AnimatedHeaderValue = new Animated.Value(0);
}
render() {
const AnimateHeaderBackgroundColor = this.AnimatedHeaderValue.interpolate(
{
inputRange: [ 0, ( Header_Maximum_Height - Header_Minimum_Height ) ],
outputRange: [ '#009688', '#00BCD4' ],
extrapolate: 'clamp'
});
const AnimateHeaderHeight = this.AnimatedHeaderValue.interpolate(
{
inputRange: [ 0, ( Header_Maximum_Height - Header_Minimum_Height ) ],
outputRange: [ Header_Maximum_Height, Header_Minimum_Height ],
extrapolate: 'clamp'
});
return (
<SafeAreaView style={{flex:1}}>
<Animated.View style={{height:AnimateHeaderHeight,width:'100%', backgroundColor:'gray'}}>
<Text style={{color:'white'}}> Collapsible Expandable Header </Text>
</Animated.View>
<Animated.ScrollView
scrollEventThrottle = { 16 }
onScroll = { Animated.event(
[{ nativeEvent: { contentOffset: { y: this.AnimatedHeaderValue }}}]
)}>
<ImageBackground
style={{width:375, height:400}}
source={require('./assets/pizza.jpg')}>
</ImageBackground>
</Animated.ScrollView>
</SafeAreaView>
);
}
}
const tabBarHeight = 100
const AppTabNavigator = createMaterialTopTabNavigator({
Home:{
screen:HomeScreen,
navigationOptions: {
header: null,
tabBarVisible:true,
activeTintColor: '#e91e63',
}
}, {
tabBarOptions: {
showLabel: true,
style: {
backgroundColor: 'rgba(22, 22, 22, 0)',
position: 'absolute',
Top: Dimensions.get('window').height-tabBarHeight,
left:0,
right:0,
//I initially set the margin to 45 but as I scroll up How can I set the marginTop to 0 when I reach the top screen.
marginTop:45
},
labelStyle:{
fontSize:15,
color:"white"
}
}
}
)
I also tried marginTop to this.AnimatedHeaderValue but doesn't seem to work. Any advise or comments would be really helpful.
You can add a listener on the Animated.event that would allow you to get the value of your y:
<Animated.ScrollView
scrollEventThrottle={16}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.AnimatedHeaderValue }}}],
{
useNativeDriver: true,
listener: event => {
const offsetY = event.nativeEvent.contentOffset.y
this.onScrollChange(offsetY)
}
},
)}
>
<ImageBackground
style={{ width: 375, height: 400 }}
source={require('./assets/pizza.jpg')}
/>
</Animated.ScrollView>
Here, you just need to define the onScrollChange in your component. Because your marginTop is in your top-level <App />, it will be a little tricky to change, so you could potentially use Redux or a Context to update and use this value.
You could also put the margin at the same level and use a state, but that would force you to do the same for every page depending on your architecture.
Because you need to change on runtime the tabBarOptions, you're going to need to create and provide a custom tabBarComponent to your navigator:
const AppTabNavigator = createMaterialTopTabNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: {
header: null,
tabBarVisible: true,
activeTintColor: '#e91e63',
},
},
},
{
tabBarComponent: CustomTabBar
},
)
This component will extend the default component used by react-navigation, and hook into a state.
import React from 'react'
import { MaterialTopTabBar } from 'react-navigation'
export default ({ hasMargin, ...props }) => (
<MaterialTopTabBar
{...props}
showLabel
labelStyle={{
fontSize: 15,
color: 'white',
}}
style={{
backgroundColor: 'rgba(22, 22, 22, 0)',
position: 'absolute',
top: Dimensions.get('window').height-tabBarHeight,
left: 0,
right: 0,
marginTop: hashMargin ? 45 : 0,
}}
/>
)
The problem here is that you won't have the variable hasMargin. You will need to either choose to either connect your component using Redux or use a React context. Both require some understanding and configuration, so you might need to read up a bit on them. Once it's done, define onScrollChange to change your context or dispatch a redux action.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With