Created
June 8, 2019 16:30
-
-
Save VojtaSim/6203b217f3819c96ab0de2f1b37427a9 to your computer and use it in GitHub Desktop.
react-navigation: Shazam-like TabBar with dots
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 characters
import React, { Component } from 'react'; | |
import { View, SafeAreaView, Animated } from 'react-native'; | |
import { NavigationState } from 'react-navigation'; | |
import { SceneRendererProps } from 'react-native-tab-view'; | |
import Styles, { DOT_SIZE, DOT_MARGIN, BAR_WIDTH } from './styles'; | |
type ScreenDotsProps = SceneRendererProps & { | |
state: NavigationState | |
}; | |
type ScreenDotsState = { | |
barWidth: Animated.AnimatedInterpolation, | |
barPosition: Animated.AnimatedSubtraction, | |
} | |
export default class ScreenDots extends Component<ScreenDotsProps, ScreenDotsState> { | |
constructor(props) { | |
super(props); | |
const barWidth = this.getBarWithInterpolation(); | |
this.state = { | |
barWidth, | |
barPosition: this.getBarPositionInterpolation(barWidth) | |
}; | |
} | |
render() { | |
const { routes } = this.props.navigation.state; | |
const { barWidth, barPosition } = this.state; | |
return ( | |
<SafeAreaView style={Styles.container}> | |
<View style = {Styles.dotsContainer}> | |
{routes.map((route, index) => ( | |
<View key={route.key} style={[ | |
Styles.dot, | |
index === 0 ? null : { marginLeft: DOT_MARGIN } | |
]} /> | |
))} | |
<Animated.View style = {[ | |
Styles.bar, | |
{ | |
width: barWidth, | |
left: barPosition | |
} | |
]}/> | |
</View> | |
</SafeAreaView> | |
) | |
} | |
getBarWithInterpolation() { | |
const { position, navigation } = this.props; | |
const { routes } = navigation.state; | |
const indexPhase = [0.3, 0.7, 1]; | |
const widthPhase = [BAR_WIDTH, BAR_WIDTH, DOT_SIZE]; | |
const routeIndexes = routes.reduce( | |
(indexes, _, index) => indexes.concat(indexPhase.map(i => index + i)), | |
[0] | |
); | |
return position.interpolate({ | |
inputRange: routeIndexes, | |
outputRange: routes.reduce(phases => phases.concat(widthPhase), [DOT_SIZE]), | |
extrapolate: 'clamp' | |
}); | |
} | |
getBarPositionInterpolation(widthInterpolation) { | |
const { position, navigation } = this.props; | |
const { routes } = navigation.state; | |
const routeIndexes = routes.map((_, index) => index); | |
return Animated.subtract( | |
position.interpolate({ | |
inputRange: routeIndexes, | |
outputRange: routes.map((_, index) => (DOT_SIZE + DOT_MARGIN) * index), | |
extrapolate: 'clamp' | |
}), | |
Animated.divide(widthInterpolation, 2) | |
); | |
} | |
} |
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 characters
import { StyleSheet } from 'react-native'; | |
export const DOT_SIZE = 10; | |
export const DOT_MARGIN = 14; | |
export const BAR_WIDTH = DOT_SIZE + DOT_MARGIN; | |
export default StyleSheet.create({ | |
container: { | |
position: 'absolute', | |
left: 0, | |
top: 0, | |
right: 0, | |
flexDirection: 'row', | |
flexWrap: 'nowrap', | |
justifyContent: 'center', | |
zIndex: 100, | |
}, | |
dotsContainer: { | |
position: 'relative', | |
flexDirection: 'row', | |
flexWrap: 'nowrap', | |
justifyContent: 'center' | |
}, | |
dot: { | |
backgroundColor: '#000', | |
borderRadius: DOT_SIZE, | |
height: DOT_SIZE, | |
width: DOT_SIZE, | |
opacity: 0.5 | |
}, | |
bar: { | |
backgroundColor: '#000', | |
borderRadius: DOT_SIZE, | |
height: DOT_SIZE, | |
opacity: 1, | |
position: 'absolute', | |
bottom: 0, | |
marginLeft: DOT_SIZE / 2 | |
}, | |
indicator: { | |
position: 'absolute', | |
bottom: 0, | |
left: 0, | |
backgroundColor: 'red', | |
height: 3, | |
} | |
}); |
Do you have all the necessary dependencies installed and set up? (react-navigation and react-native-tab-view)
Hello, how do I use this? I want to implement it with react-native-tab-view. Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for this!
Could you please help with a problem I'm having? It shows error:
https://share.getcloudapp.com/d5ueKPBQ
Line 59 is https://share.getcloudapp.com/kpumjNB8.
I've just started learning the react-native, so perhaps that's why I couldn't solve this. Any help is greatly appreciated.
Thanks,
Metin