UNPKG

react-native-ui-lib

Version:

UI Components Library for React Native ###### Lateset version support RN44

143 lines (124 loc) 3.58 kB
import React from 'react'; import {StyleSheet, ViewPropTypes, Animated} from 'react-native'; import _ from 'lodash'; import PropTypes from 'prop-types'; import {Colors} from '../../style'; import {BaseComponent} from '../../commons'; import View from '../view'; import TabBarItem from './TabBarItem'; export default class TabBar extends BaseComponent { static displayName = 'TabBar'; static propTypes = { ...ViewPropTypes.height, /** * current selected tab index */ selectedIndex: PropTypes.number, /** * custom style for the tab bar */ style: ViewPropTypes.style, /** * custom style for the selected indicator */ indicatorStyle: ViewPropTypes.style, /** * disable the animated transition of the tab indicator */ disableAnimatedTransition: PropTypes.bool, } static defaultProps = { selectedIndex: 0, height: 51, } constructor(props) { super(props); const childrenCount = React.Children.count(this.props.children); this.state = { selectedIndex: props.selectedIndex, selectedIndicatorPosition: new Animated.Value(this.calcPosition(props.selectedIndex, childrenCount)), }; } generateStyles() { this.styles = createStyles(this.props); } calcPosition(index, tabsCount) { const position = index * (100 / tabsCount); return position; } calcIndicatorWidth() { const childrenCount = React.Children.count(this.props.children); if (childrenCount === 0) { return '0%'; } const width = Math.floor(100 / childrenCount); return `${width}%`; } onSelectingTab(index) { const {disableAnimatedTransition} = this.props; const {selectedIndicatorPosition} = this.state; const newPosition = this.calcPosition(index, this.props.children.length); if (disableAnimatedTransition) { selectedIndicatorPosition.setValue(newPosition); } else { Animated.spring(selectedIndicatorPosition, { toValue: this.calcPosition(index, this.props.children.length), tension: 30, friction: 8, }).start(); } this.setState({ selectedIndex: index, }); } renderChildren() { const {selectedIndex} = this.state; const children = React.Children.map(this.props.children, (child, index) => { return React.cloneElement(child, { selected: selectedIndex === index, onPress: () => { this.onSelectingTab(index); _.invoke(child.props, 'onPress'); }, }); }); return children; } renderSelectedIndicator() { const {indicatorStyle} = this.props; const {selectedIndicatorPosition} = this.state; const width = this.calcIndicatorWidth(); const left = selectedIndicatorPosition.interpolate({ inputRange: [0, 100], outputRange: ['0%', '100%'], }); return ( <Animated.View style={[this.styles.selectedIndicator, {left, width}, indicatorStyle]}/> ); } render() { const {height, style} = this.props; return ( <View style={[this.styles.container, style]} bg-white row height={height}> {this.renderChildren()} {this.renderSelectedIndicator()} </View> ); } } function createStyles() { return StyleSheet.create({ container: { borderBottomWidth: StyleSheet.hairlineWidth, borderColor: Colors.dark70, }, selectedIndicator: { position: 'absolute', bottom: 0, left: 0, borderBottomWidth: 1.5, borderColor: Colors.blue30, }, }); } TabBar.Item = TabBarItem;