Created
August 8, 2019 04:20
-
-
Save bookjan/412d88ebd6b98f8ed49900be946668bf 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