Created
September 12, 2016 16:22
-
-
Save knowbody/1c665a5d1cc7c603bd9b1f111d8bba6c to your computer and use it in GitHub Desktop.
ScrollTabBar for react-native-tab-view
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 { | |
| Animated, | |
| Dimensions, | |
| StyleSheet, | |
| ScrollView, | |
| TouchableOpacity, | |
| View, | |
| Text, | |
| } from 'react-native'; | |
| import shallowCompare from 'react-addons-shallow-compare'; | |
| import Icon from 'react-native-vector-icons/Ionicons'; | |
| import TouchableItem from './TouchableItem'; | |
| const VISIBLE_TABS = 5.5; | |
| const styles = StyleSheet.create({ | |
| tabbar: { | |
| paddingTop: 20, | |
| backgroundColor: 'black', | |
| flexDirection: 'row', | |
| flexWrap: 'nowrap', | |
| elevation: 4, | |
| }, | |
| tabLabel: { | |
| color: 'white', | |
| margin: 8, | |
| fontSize: 20, | |
| fontWeight: '500' | |
| }, | |
| tab: { | |
| width: Dimensions.get('window').width / VISIBLE_TABS, | |
| alignSelf: 'center', | |
| }, | |
| tabitem: { | |
| flex: 1, | |
| padding: 8, | |
| alignItems: 'center', | |
| justifyContent: 'center', | |
| }, | |
| indicator: { | |
| backgroundColor: 'white', | |
| position: 'absolute', | |
| left: 0, | |
| bottom: 0, | |
| right: 0, | |
| height: 2, | |
| }, | |
| }); | |
| export default class ScrollTabBar extends Component { | |
| static defaultProps = { | |
| renderLabel: ({ route }) => | |
| route.title ? <Text style={styles.tabLabel}>{route.title}</Text> : null, | |
| renderIcon: ({ route, focused }) => | |
| route.icon ? ( | |
| <Icon | |
| size={route.iconSize || 24} | |
| color={route.iconColor || '#fff'} | |
| name={route.iconName || 'md-clipboard'} | |
| /> | |
| ) : null, | |
| renderIndicator: (props) => { | |
| const { layout: { width }, position } = props; | |
| const { routes } = props.navigationState; | |
| const translateX = Animated.multiply(position, new Animated.Value(width / VISIBLE_TABS)); | |
| return ( | |
| <Animated.View | |
| style={[ | |
| styles.indicator, | |
| { width: width / VISIBLE_TABS, transform: [{ translateX }] } | |
| ]} | |
| /> | |
| ); | |
| } | |
| }; | |
| shouldComponentUpdate(nextProps, nextState) { | |
| return shallowCompare(this, nextProps, nextState); | |
| } | |
| render() { | |
| const { position } = this.props; | |
| const { routes, index } = this.props.navigationState; | |
| const inputRange = routes.map((x, i) => i); | |
| return ( | |
| <View style={[styles.tabbar, this.props.style]}> | |
| <TouchableOpacity | |
| style={styles.tab} | |
| onPress={() => this.props.onBack()} | |
| > | |
| <Icon | |
| size={30} | |
| color="#fff" | |
| style={{ alignSelf: 'center' }} | |
| name="ios-arrow-down" | |
| /> | |
| </TouchableOpacity> | |
| <ScrollView | |
| horizontal | |
| showsHorizontalScrollIndicator={false} | |
| > | |
| {routes.map((route, i) => { | |
| const focused = index === i; | |
| const outputRange = inputRange.map(inputIndex => inputIndex === i ? 1 : 0.7); | |
| const opacity = position.interpolate({ | |
| inputRange, | |
| outputRange, | |
| }); | |
| const scene = { | |
| route, | |
| focused, | |
| index: i, | |
| }; | |
| const icon = this.props.renderIcon ? this.props.renderIcon(scene) : null; | |
| const label = this.props.renderLabel ? this.props.renderLabel(scene) : null; | |
| let tabStyle; | |
| if (icon) { | |
| if (label) { | |
| tabStyle = { marginTop: 8 }; | |
| } else { | |
| tabStyle = { margin: 8 }; | |
| } | |
| } | |
| return ( | |
| <TouchableItem | |
| key={route.key} | |
| style={styles.tab} | |
| onPress={() => this.props.jumpToIndex(i)} | |
| > | |
| <Animated.View style={[styles.tabitem, { opacity }, tabStyle, this.props.tabStyle]}> | |
| {this.props.renderIcon ? this.props.renderIcon(scene) : null} | |
| {this.props.renderLabel ? this.props.renderLabel(scene) : null} | |
| </Animated.View> | |
| </TouchableItem> | |
| ); | |
| })} | |
| {this.props.renderIndicator ? this.props.renderIndicator(this.props) : null} | |
| </ScrollView> | |
| </View> | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment