Forked from bookjan/IndicatorWrapContentExample.js
Created
November 17, 2019 11:05
-
-
Save adriancbo/6abcdba484bb5d1c7e73434768946215 to your computer and use it in GitHub Desktop.
Indicator Wrap Content Example by [email protected]
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
/* @flow */ | |
import * as React from 'react'; | |
import { | |
StyleSheet, Text | |
} from 'react-native'; | |
import { | |
TabBar, TabView | |
} from 'react-native-tab-view'; | |
import Animated from 'react-native-reanimated'; | |
const SCREEN_WIDTH_RATIO = 3.75; | |
const NAV_STATE_MAP = { | |
index : 0, | |
routes: [ | |
{ | |
key : 'spend', | |
title : 'Spend', | |
tabBarTextWidth: 0 | |
}, | |
{ | |
key : 'refund', | |
title : 'Refund', | |
tabBarTextWidth: 0 | |
} | |
] | |
}; | |
type State = { | |
navigationState: Object, | |
}; | |
type Props = { | |
scene: Object, | |
style?: Object, | |
onIndexChange: Function, | |
} | |
export default class IndicatorWrapContentTabView extends React.Component<Props, State> { | |
state = { navigationState: NAV_STATE_MAP }; | |
_renderIndicator = (props: Object) => { | |
const { | |
position, navigationState, getTabWidth | |
} = props; | |
const inputRange = [ | |
0, | |
1 | |
]; | |
const translateX = Animated.interpolate(position, { | |
inputRange : inputRange, | |
outputRange: inputRange.map(x => { | |
const i = Math.round(x); | |
return i * getTabWidth(i) ; | |
}) | |
}); | |
const currentIndicatorWidth = navigationState.routes[navigationState.index].tabBarTextWidth; | |
return ( | |
<Animated.View | |
style={[ | |
styles.container, | |
{ | |
width : `${100 / navigationState.routes.length}%`, | |
transform: [{ translateX }] | |
} | |
]} | |
> | |
<Animated.View | |
style={[ | |
styles.indicator, | |
{ width: currentIndicatorWidth } | |
]} | |
/> | |
</Animated.View> | |
); | |
}; | |
_renderTabBarLabel = ({ | |
route, focused | |
}: Object) => ( | |
<Text | |
onLayout={event => { | |
const { width } = event.nativeEvent.layout; | |
const currentRouteKey = route.key; | |
this.setState(prevState => { | |
const routes = prevState.navigationState.routes.map(route => { | |
if (route.key === currentRouteKey) { | |
route.tabBarTextWidth = Math.round(width); | |
} | |
return route; | |
}); | |
return { | |
navigationState: { | |
...prevState.navigationState, | |
index: prevState.navigationState.index, | |
routes | |
} | |
}; | |
}); | |
}} | |
style={ | |
focused | |
? { color: 'rgb(25,29,33)' } | |
: { color: 'rgb(174,179,192)' } | |
} | |
> | |
{route.title} | |
</Text> | |
); | |
_renderTabBar = (props: Object) => { | |
let tabWidthStyle = Math.round(Dimensions.get('window').width / SCREEN_WIDTH_RATIO); | |
return ( | |
<TabBar | |
{...props} | |
renderLabel={this._renderTabBarLabel} | |
renderIndicator={this._renderIndicator} | |
style={styles.tabbar} | |
tabStyle={[ | |
tabWidthStyle, { height: 45 } | |
]} | |
contentContainerStyle={{ | |
flexDirection: 'row', | |
flexWrap : 'wrap' | |
}} | |
/> | |
); | |
}; | |
render() { | |
return ( | |
<TabView | |
style={this.props.style} | |
navigationState={this.state.navigationState} | |
renderScene={this.props.scene} | |
lazy={true} | |
renderTabBar={this._renderTabBar} | |
onIndexChange={(index) => { | |
this.setState({ | |
navigationState: { | |
...this.state.navigationState, | |
index | |
} | |
}); | |
this.props.onIndexChange && this.props.onIndexChange(index); | |
}} | |
/> | |
); | |
} | |
} | |
const styles = StyleSheet.create({ | |
tabbar : { backgroundColor: 'white' }, | |
container: { | |
flex : 1, | |
alignItems : 'center', | |
justifyContent: 'flex-end' | |
}, | |
indicator: { | |
height : 3, | |
backgroundColor: 'orange' | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment