diff --git a/README.md b/README.md index e04b24d..e869578 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,19 @@ This component requires just 2 props. `onPress` function, that should handle ren ```JSX { this._handlePress(tabIndex) }} - values={[ - { title: "News", icon: require("./assets/news.png") }, - { title: "Requests", icon: require("./assets/requests.png") }, - { title: "Events", icon: require("./assets/events.png") }, - { title: "Members", icon: require("./assets/members.png") }, - { title: "Account", icon: require("./assets/account.png") } - ]} + iconStyle={{ width: 50, height: 50 }} + tintColor="blue" + onPress={(tabIndex) => { + console.warn(tabIndex); + }} + isRtl={ true } + values={[ + { title: "Home", icon: require("./home.png"), tintColor: curTab == 0 ? "red" : "blue", default: true }, + { title: "Home1", icon: require("./home.png"), tintColor: curTab == 1 ? "red" : "blue", }, + { title: "Home2", icon: require("./home.png"), tintColor: curTab == 2 ? "red" : "blue", }, + { title: "Home3", icon: require("./home.png"), tintColor: curTab == 3 ? "red" : "blue", }, + { title: "Home4", icon: require("./home.png"), tintColor: curTab == 4 ? "red" : "blue", }, + ]} /> ``` @@ -48,6 +53,28 @@ This component requires just 2 props. `onPress` function, that should handle ren Optionally you can pass `tintColor` prop, to adjust styling to your app. +1. iconStyle => Now you can style your icon used in navigator without editing core module + +2. isRtl => New feature for apps that requires rtl. + +3. tintColor => tintColor in values let's you add specific color for each icon + +4. default => Now you can setdefault tab by passing additional parameter in values object + +5. containerBackgroundColor => Now you can change default container background color by passing color value to `containerBackgroundColor` prop + +6. itemMaskBackgroundColor => Now you can change default mask color by passing color value to `itemMaskBackgroundColor` prop + +### Extra paramters added +| Property | Type | Default | Description | Required | +| ------------- | ------------- | ------------- | ------------- | ------------- | +| iconStyle | ImageStyle | { width: 20, height: 20 } | iconStyle prop allows you to customize the icon used in bottom tab bar | false | +| isRtl | Boolean | false | If you have rtl in your app, set valueto true and the bottom tab bar will show in reverse order | false | +| tintColor | String | Black | You can assign custom color for each icon by passing tintColor prop along with title and icon. This can be used to assign unique color for active tab | true | +| default | Boolean | false | Now default tab can be set by passing default prop along with title and icon. This can be used to focus aspecific tab before any user interaction | true | +| containerBackgroundColor | String | white | Now you can change default container background color by passing color value to `containerBackgroundColor` prop. It accespts string and hex values | false | +| itemMaskBackgroundColor | String | white | Now you can change default mask color by passing color value to `itemMaskBackgroundColor` prop. It accespts string and hex values | false | + ## Author [Patryk Mierzejewski](https://github.com/pmierzejewski) diff --git a/index.js b/index.js index 833d6ba..dc7c895 100644 --- a/index.js +++ b/index.js @@ -2,272 +2,298 @@ import React, { Component } from "react"; import { - TouchableWithoutFeedback, - Animated, - Easing, - Image + TouchableWithoutFeedback, + Animated, + Easing, + Image, + ImageStyle, + ImagePropertiesSourceOptions, } from "react-native"; import PropTypes from "prop-types"; import ViewOverflow from "react-native-view-overflow"; const AnimatedViewOverflow = Animated.createAnimatedComponent(ViewOverflow); -class TabBar extends Component { - constructor(props) { - super(props); - this.animatedItemValues = []; - this.animatedBubbleValues = []; - this.animatedMiniBubbleValues = []; - this.animatedImageValues = []; - this.props.values.forEach((item, index) => { - this.animatedItemValues[index] = new Animated.Value(0); - this.animatedBubbleValues[index] = new Animated.Value(0); - this.animatedImageValues[index] = new Animated.Value(0); - this.animatedMiniBubbleValues[index] = new Animated.Value(0); - }); - } +interface valuesProp { + title: String, + icon: ImagePropertiesSourceOptions, + tintColor: String, + default: Boolean +} + +interface TabBarProps { + iconStyle: ImageStyle, + values: Array, + isRtl: Boolean, + containerBackgroundColor: String, + itemMaskBackgroundColor: String +} + +class TabBar extends Component { + constructor(props) { + super(props); + + this.state = { + lastSelectedIndex: null + }; - static defaultProps = { - tintColor: "rgb(76, 83, 221)" - }; + this.animatedItemValues = []; + this.animatedBubbleValues = []; + this.animatedMiniBubbleValues = []; + this.animatedImageValues = []; + this.props.values.forEach((item, index) => { + this.animatedItemValues[index] = new Animated.Value(item.default ? -30 : 0); + this.animatedBubbleValues[index] = new Animated.Value(item.default ? 1 : 0); + this.animatedImageValues[index] = new Animated.Value(item.default ? 1 : 0); + this.animatedMiniBubbleValues[index] = new Animated.Value(item.default ? 1 : 0); + item.default && (this.state = { lastSelectedIndex: index }) + }); + } - state = { - lastSelectedIndex: null - }; + static defaultProps = { + tintColor: "rgb(76, 83, 221)", + iconStyle: { width: 20, height: 20 }, + isRtl: false, + containerBackgroundColor: "white", + itemMaskBackgroundColor: "white", + }; - _renderButtons = () => { - return this.props.values.map((item, index) => { - const animatedItemStyle = { - transform: [{ translateY: this.animatedItemValues[index] }] - }; + _renderButtons = () => { + const { iconStyle, values } = this.props + return values.map((item: valuesProp, index) => { + const animatedItemStyle = { + transform: [{ translateY: this.animatedItemValues[index] }] + }; - const animatedBubbleScaleValues = this.animatedBubbleValues[ - index - ].interpolate({ - inputRange: [0, 0.25, 0.4, 0.525, 0.8, 1], - outputRange: [0.01, 3, 1.65, 1.65, 3.2, 3] - }); + const animatedBubbleScaleValues = this.animatedBubbleValues[ + index + ].interpolate({ + inputRange: [0, 0.25, 0.4, 0.525, 0.8, 1], + outputRange: [0.01, 3, 1.65, 1.65, 3.2, 3] + }); - const animatedColorValues = this.animatedImageValues[index].interpolate({ - inputRange: [0, 1], - outputRange: [this.props.tintColor, "rgb(255, 255, 255)"] - }); + const animatedColorValues = this.animatedImageValues[index].interpolate({ + inputRange: [0, 1], + outputRange: [this.props.tintColor, "rgb(255, 255, 255)"] + }); - const animatedBubbleStyle = { - transform: [{ scale: animatedBubbleScaleValues }] - }; + const animatedBubbleStyle = { + transform: [{ scale: animatedBubbleScaleValues }] + }; - const animatedImageStyle = { - tintColor: animatedColorValues - }; + const animatedImageStyle = { + tintColor: animatedColorValues + }; - const animatedMiniBubbleTranslateValues = this.animatedMiniBubbleValues[ - index - ].interpolate({ - inputRange: [0, 1], - outputRange: [13, 0] - }); + const animatedMiniBubbleTranslateValues = this.animatedMiniBubbleValues[ + index + ].interpolate({ + inputRange: [0, 1], + outputRange: [13, 0] + }); - const animatedMiniBubbleHeightValues = this.animatedMiniBubbleValues[ - index - ].interpolate({ - inputRange: [0, 0.01, 1], - outputRange: [0, 1, 1] - }); + const animatedMiniBubbleHeightValues = this.animatedMiniBubbleValues[ + index + ].interpolate({ + inputRange: [0, 0.01, 1], + outputRange: [0, 1, 1] + }); - const animatedMiniBubbleStyle = { - opacity: animatedMiniBubbleHeightValues, - transform: [{ translateY: animatedMiniBubbleTranslateValues }] - }; + const animatedMiniBubbleStyle = { + opacity: animatedMiniBubbleHeightValues, + transform: [{ translateY: animatedMiniBubbleTranslateValues }] + }; - const animatedTitleValues = this.animatedBubbleValues[index].interpolate({ - inputRange: [0, 1], - outputRange: [60, 60] - }); + const animatedTitleValues = this.animatedBubbleValues[index].interpolate({ + inputRange: [0, 1], + outputRange: [60, 60] + }); - const animatedTitleStyle = { - transform: [{ translateY: animatedTitleValues }] - }; + const animatedTitleStyle = { + transform: [{ translateY: animatedTitleValues }] + }; - return ( - { - if (index === this.state.lastSelectedIndex) { - return; - } + return ( + { + if (index === this.state.lastSelectedIndex) { + return; + } - this.startAnimation(index); + this.startAnimation(index); - if (this.state.lastSelectedIndex !== null) { - this.endAnimation(this.state.lastSelectedIndex); - } + if (this.state.lastSelectedIndex !== null) { + this.endAnimation(this.state.lastSelectedIndex); + } - this.setState({ - lastSelectedIndex: index - }); + this.setState({ + lastSelectedIndex: index + }); - this.props.onPress(index); - }} - > - - - - - - - - {item.title} - - - - - ); - }); - }; + this.props.onPress(index); + }} + > + + + + + {/* ooooo {JSON.stringify(item.default)} */} + + + + {item.title} + + + + + ); + }); + }; - startAnimation = index => { - Animated.parallel([ - Animated.timing(this.animatedItemValues[index], { - toValue: -30, - duration: 500, - delay: 300, - easing: Easing.in(Easing.elastic(1.5)), - useNativeDriver: true - }), - Animated.timing(this.animatedMiniBubbleValues[index], { - toValue: 1, - duration: 1000, - delay: 300, - useNativeDriver: true - }), - Animated.timing(this.animatedBubbleValues[index], { - toValue: 1, - duration: 800, - easing: Easing.inOut(Easing.out(Easing.ease)), - useNativeDriver: true - }), - Animated.timing(this.animatedImageValues[index], { - toValue: 1, - duration: 800 - }) - ]).start(); - }; + startAnimation = index => { + Animated.parallel([ + Animated.timing(this.animatedItemValues[index], { + toValue: -30, + duration: 500, + delay: 300, + easing: Easing.in(Easing.elastic(1.5)), + useNativeDriver: true + }), + Animated.timing(this.animatedMiniBubbleValues[index], { + toValue: 1, + duration: 1000, + delay: 300, + useNativeDriver: true + }), + Animated.timing(this.animatedBubbleValues[index], { + toValue: 1, + duration: 800, + easing: Easing.inOut(Easing.out(Easing.ease)), + useNativeDriver: true + }), + Animated.timing(this.animatedImageValues[index], { + toValue: 1, + duration: 800 + }) + ]).start(); + }; - endAnimation = index => { - Animated.parallel([ - Animated.timing(this.animatedItemValues[index], { - toValue: 0, - duration: 400, - delay: 350, - useNativeDriver: true - }), - Animated.timing(this.animatedMiniBubbleValues[index], { - toValue: 0, - duration: 1, - useNativeDriver: true - }), - Animated.timing(this.animatedBubbleValues[index], { - toValue: 0, - duration: 750, - easing: Easing.out(Easing.ease), - useNativeDriver: true - }), - Animated.timing(this.animatedImageValues[index], { - toValue: 0, - duration: 400, - delay: 350 - }) - ]).start(); - }; + endAnimation = index => { + Animated.parallel([ + Animated.timing(this.animatedItemValues[index], { + toValue: 0, + duration: 400, + delay: 350, + useNativeDriver: true + }), + Animated.timing(this.animatedMiniBubbleValues[index], { + toValue: 0, + duration: 1, + useNativeDriver: true + }), + Animated.timing(this.animatedBubbleValues[index], { + toValue: 0, + duration: 750, + easing: Easing.out(Easing.ease), + useNativeDriver: true + }), + Animated.timing(this.animatedImageValues[index], { + toValue: 0, + duration: 400, + delay: 350 + }) + ]).start(); + }; - render() { - return ( - - {this._renderButtons()} - - ); - } + render() { + const { isRtl } = this.props + return ( + + {this._renderButtons()} + + ); + } } TabBar.propTypes = { - onPress: PropTypes.func.isRequired, - values: PropTypes.arrayOf( - PropTypes.shape({ - title: PropTypes.string.isRequired, - icon: PropTypes.number.isRequired - }) - ), - tintColor: PropTypes.string + onPress: PropTypes.func.isRequired, + values: PropTypes.arrayOf( + PropTypes.shape({ + title: PropTypes.string.isRequired, + icon: PropTypes.number.isRequired, + tintColor: PropTypes.string.isRequired, + default: PropTypes.bool + }) + ), + tintColor: PropTypes.string, + isRtl: PropTypes.bool }; const styles = { - container: { - flexDirection: "row", - height: 60, - width: "100%", - justifyContent: "space-around", - alignItems: "center", - backgroundColor: "white" - }, - item: { - backgroundColor: "white", - borderRadius: 30, - height: 60, - width: 60, - alignItems: "center", - justifyContent: "center" - }, - itemMask: { - tintColor: "white", - position: "absolute" - }, - bubble: { - position: "absolute", - alignSelf: "center", - height: 17, - width: 17, - backgroundColor: "#4C53DD", - borderRadius: 8.5 - }, - miniBubble: { - position: "absolute", - alignSelf: "center", - width: 22, - height: 22, - backgroundColor: "#4C53DD", - borderRadius: 11 - }, - titleContainer: { - position: "absolute", - top: 0, - left: 0, - right: 0, - flex: 1, - justifyContent: "center", - alignItems: "center" - } + container: { + height: 60, + width: "100%", + justifyContent: "space-around", + alignItems: "center" + }, + item: { + backgroundColor: "transparent", + borderRadius: 30, + height: 60, + width: 60, + alignItems: "center", + justifyContent: "center" + }, + itemMask: { + position: "absolute" + }, + bubble: { + position: "absolute", + alignSelf: "center", + height: 17, + width: 17, + backgroundColor: "#4C53DD", + borderRadius: 8.5 + }, + miniBubble: { + position: "absolute", + alignSelf: "center", + width: 22, + height: 22, + backgroundColor: "#4C53DD", + borderRadius: 11 + }, + titleContainer: { + position: "absolute", + top: 0, + left: 0, + right: 0, + flex: 1, + justifyContent: "center", + alignItems: "center" + } }; export default TabBar;