├── .npmignore ├── LICENSE ├── README.md ├── RadioButtonRN.js ├── example ├── index.js └── rbrn.gif └── package.json /.npmignore: -------------------------------------------------------------------------------- 1 | /example -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 sramezani 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # radio-buttons-react-native 2 | Animated radio buttons component for react native 3 | 4 | 4 types animation when click on any items of radio button 5 | 6 | 7 | # DEMO 8 | ![](https://user-images.githubusercontent.com/33284430/66270229-7ef73200-e883-11e9-98bf-4dddd01cd78c.gif) 9 | 10 | # install 11 | npm install radio-buttons-react-native --save 12 | 13 | # Usage 14 | import RadioButtonRN from 'radio-buttons-react-native'; 15 | 16 | const data = [ 17 | { 18 | label: 'data 1' 19 | }, 20 | { 21 | label: 'data 2' 22 | } 23 | ]; 24 | 25 | console.log(e)} 28 | /> 29 | 30 | see this simple [example](https://github.com/sramezani/radio-buttons-react-native/blob/master/example/index.js) to find how use this component. 31 | 32 |

with customize icon:

33 | 34 | // import icon from any library 35 | import Icon from 'react-native-vector-icons/FontAwesome'; 36 | 37 | console.log(e)} 40 | icon={ 41 | 46 | } 47 | /> 48 | 49 | 50 | 51 | 52 | # Properties 53 | 54 | | Prop | Description | Default | 55 | | ------------- | ------------- | ------------- | 56 | | data | radio buttons label array, you can use any data in object, label is necessary for showing in radio button | [] | 57 | | selectedBtn | callback when radio button clicked | - | 58 | | icon | you can use any icon for button, see the example | - | 59 | | box | box of for items | true | 60 | | initial | The number of selected radio button. start from 1 for first item of array. This is used when this component is activated. | -1 | 61 | | animationTypes | the animations when click on item, Valid values: 'zoomIn', 'pulse', 'shake', 'rotate', you can use one or more of this value for exaple: ['pulse'] or ['pulse', 'rotate'] | [] | 62 | | duration | For how long the animation will run (milliseconds) | 500 | 63 | | style | style for all RadioButtonRN | {} | 64 | | boxStyle | style for box | {} | 65 | | textStyle | style for label text | {} | 66 | | circleSize | circle size for unselected items and whitout icon selected size | 18 | 67 | | activeColor | color of active button and box border | '#03a9f4' | 68 | | deactiveColor | color of deactive button | '#e2e2e2' | 69 | | boxActiveBgColor | background color of active item, when box is true | '#e1f5fe33' | 70 | | boxDeactiveBgColor | background color of deactive items, when box is true | '#fff' | 71 | | textColor | label color | '#383838' | 72 | 73 | # Contributing 74 | Yes of course! Welcome :) 75 | 76 | # License 77 | [MIT](https://github.com/sramezani/radio-buttons-react-native/blob/master/LICENSE) 78 | -------------------------------------------------------------------------------- /RadioButtonRN.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { StyleSheet, View, Text, Animated, TouchableOpacity } from 'react-native'; 4 | 5 | 6 | class RadioButtonRN extends React.Component { 7 | 8 | constructor(props) { 9 | super(props); 10 | 11 | this.state = { 12 | activeIndex: -1, 13 | fadeAnim: new Animated.Value(0), 14 | animations: [] 15 | }; 16 | // this.fadeAnim = new Animated.Value(0); 17 | 18 | this.animations = [ 19 | { 20 | name: 'zoomIn', 21 | animation: { 22 | scale: this.state.fadeAnim.interpolate({ 23 | inputRange: [0, 1], 24 | outputRange: [0, 1] 25 | }) 26 | } 27 | }, 28 | { 29 | name: 'pulse', 30 | animation: { 31 | scale: this.state.fadeAnim.interpolate({ 32 | inputRange: [0, 0.4, 0.7, 1], 33 | outputRange: [0.7, 1, 1.3, 1] 34 | }) 35 | } 36 | }, 37 | { 38 | name: 'shake', 39 | animation: { 40 | scale: this.state.fadeAnim.interpolate({ 41 | inputRange: [0, 0.2, 0.4, 0.6, 0.8, 1], 42 | outputRange: [0.8, 1.2, 0.8, 1.2, 0.8, 1] 43 | }) 44 | } 45 | }, 46 | { 47 | name: 'rotate', 48 | animation: { 49 | rotate: this.state.fadeAnim.interpolate({ 50 | inputRange: [0, 1], 51 | outputRange: ['0deg', '360deg'] 52 | }) 53 | } 54 | }, 55 | ] 56 | 57 | this._changeRadio = this._changeRadio.bind(this); 58 | this._checkAnimatons = this._checkAnimatons.bind(this); 59 | } 60 | 61 | componentDidMount() { 62 | this._checkAnimatons(); 63 | } 64 | 65 | componentDidUpdate(prevProps, prevState) { 66 | if (this.state.activeIndex === -1 && this.props.initial > 0) { 67 | const initialActive = this.props.initial - 1; 68 | this._changeRadio(this.props.data[initialActive], initialActive); 69 | } 70 | if (this.props.initial !== prevProps.initial) { 71 | const initialActive = this.props.initial - 1; 72 | this._changeRadio(this.props.data[initialActive], initialActive); 73 | } 74 | if (this.props.animationTypes !== prevProps.animationTypes) { 75 | this._checkAnimatons(); 76 | } 77 | } 78 | 79 | _checkAnimatons() { 80 | const { animationTypes } = this.props; 81 | 82 | this.setState({ animations: [] }); 83 | const newAnim = []; 84 | animationTypes && animationTypes.map((item, index) => { 85 | const itm = this.animations.find((e) => e.name === item); 86 | if (itm) { 87 | newAnim.push(itm.animation); 88 | } 89 | }) 90 | this.setState({ animations: newAnim }); 91 | } 92 | 93 | _changeRadio(item, activeIndex) { 94 | this.setState({ activeIndex }); 95 | if (activeIndex !== this.state.activeIndex) { 96 | this.fadeInAnimation(); 97 | } 98 | this.props.selectedBtn(item); 99 | } 100 | 101 | fadeInAnimation = () => { 102 | // this.fadeAnim.setValue(0) 103 | Animated.timing(this.state.fadeAnim, { 104 | toValue: 0, 105 | duration: 0, 106 | useNativeDriver: true, 107 | }).start(() => { 108 | Animated.timing(this.state.fadeAnim, { 109 | toValue: 1, 110 | duration: this.props.duration, 111 | delay: 10, 112 | useNativeDriver: true, 113 | }).start(); 114 | }); 115 | } 116 | 117 | render() { 118 | let { activeIndex, fadeAnim, animations } = this.state; 119 | let { boxStyle, style, circleSize, textStyle, data, icon, activeColor, deactiveColor, boxActiveBgColor, boxDeactiveBgColor, box, textColor } = this.props; 120 | 121 | return ( 122 | 123 | { 124 | data.map((item, index) => { 125 | return ( 126 | this._changeRadio(item, index)} 136 | > 137 | 138 | 147 | 150 | 155 | { 156 | icon ? 157 | icon 158 | : 159 | 165 | } 166 | 167 | 168 | 169 | 170 | 171 | 172 | 175 | {item.label} 176 | 177 | 178 | 179 | ) 180 | }) 181 | } 182 | 183 | ); 184 | } 185 | 186 | } 187 | 188 | /* Styles ====================================== */ 189 | const styles = StyleSheet.create({ 190 | productBox: { 191 | flexDirection: 'row', 192 | borderRadius: 7, 193 | borderWidth: 1, 194 | paddingHorizontal: 10, 195 | paddingVertical: 15, 196 | marginTop: 10 197 | }, 198 | productBoxLess: { 199 | flexDirection: 'row', 200 | marginTop: 10 201 | }, 202 | leftProductBox: { 203 | flex: 1, 204 | alignItems: 'center', 205 | justifyContent: 'center' 206 | }, 207 | centerProductBox: { 208 | flex: 6, 209 | justifyContent: 'center', 210 | alignItems: 'flex-start', 211 | paddingHorizontal:4 212 | }, 213 | circle: { 214 | borderWidth: 1, 215 | borderRadius: 10000, 216 | alignItems: 'center', 217 | justifyContent: 'center' 218 | }, 219 | icon: { 220 | borderWidth: 1, 221 | borderRadius: 10000, 222 | alignItems: 'center', 223 | justifyContent: 'center' 224 | }, 225 | circleFill: { 226 | borderWidth: 1, 227 | borderRadius: 10000 228 | } 229 | }); 230 | 231 | /* Props ======================================= */ 232 | RadioButtonRN.propTypes = { 233 | style: PropTypes.object, 234 | boxStyle: PropTypes.object, 235 | textStyle: PropTypes.object, 236 | initial: PropTypes.number, 237 | circleSize: PropTypes.number, 238 | duration: PropTypes.number, 239 | data: PropTypes.array, 240 | animationTypes: PropTypes.array, 241 | selectedBtn: PropTypes.func, 242 | activeColor: PropTypes.string, 243 | deactiveColor: PropTypes.string, 244 | // textActiveColor: PropTypes.string, 245 | // textDeactiveColor: PropTypes.string, 246 | boxActiveBgColor: PropTypes.string, 247 | boxDeactiveBgColor: PropTypes.string, 248 | textColor: PropTypes.string, 249 | box: PropTypes.bool, 250 | }; 251 | 252 | RadioButtonRN.defaultProps = { 253 | style: {}, 254 | boxStyle: {}, 255 | textStyle: {}, 256 | initial: -1, 257 | circleSize: 18, 258 | duration: 500, 259 | data: [], 260 | animationTypes: [], 261 | selectedBtn: () => {}, 262 | activeColor: '#03a9f4', 263 | deactiveColor: '#e2e2e2', 264 | boxActiveBgColor: '#e1f5fe33', 265 | boxDeactiveBgColor: '#fff', 266 | textColor: '#383838', 267 | box: true, 268 | }; 269 | 270 | /* Export Component ============================ */ 271 | export default RadioButtonRN; -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | 2 | import React from 'react'; 3 | import { StyleSheet, View, Text, TouchableOpacity } from 'react-native'; 4 | import Icon from 'react-native-vector-icons/FontAwesome'; 5 | import RadioButtonRN from 'radio-buttons-react-native'; 6 | 7 | class App extends React.Component { 8 | 9 | constructor(props) { 10 | super(props); 11 | 12 | this.state = { 13 | res: {}, 14 | example: 1 15 | }; 16 | 17 | this.colors = [ 18 | { 19 | label: 'red' 20 | }, 21 | { 22 | label: 'green' 23 | }, 24 | { 25 | label: 'blue' 26 | } 27 | ]; 28 | 29 | this._renderRadioBtn = this._renderRadioBtn.bind(this); 30 | } 31 | 32 | _renderRadioBtn() { 33 | let { example } = this.state; 34 | if (example === 1) { 35 | return ( 36 | this.setState({ res: e })} 39 | circleSize={16} 40 | /> 41 | ) 42 | } 43 | else if (example === 2) { 44 | return ( 45 | this.setState({ res: e })} 50 | circleSize={16} 51 | /> 52 | ) 53 | } 54 | else if (example === 3) { 55 | return ( 56 | this.setState({ res: e })} 60 | circleSize={16} 61 | icon={ 62 | 67 | } 68 | /> 69 | ) 70 | } 71 | else if (example === 4) { 72 | return ( 73 | this.setState({ res: e })} 78 | circleSize={16} 79 | /> 80 | ) 81 | } 82 | else if (example === 5) { 83 | return ( 84 | this.setState({ res: e })} 90 | circleSize={16} 91 | icon={ 92 | 97 | } 98 | /> 99 | ) 100 | } 101 | else if (example === 6) { 102 | return ( 103 | this.setState({ res: e })} 108 | circleSize={16} 109 | icon={ 110 | 115 | } 116 | /> 117 | ) 118 | } 119 | else if (example === 7) { 120 | return ( 121 | this.setState({ res: e })} 126 | circleSize={16} 127 | icon={ 128 | 133 | } 134 | /> 135 | ) 136 | } 137 | } 138 | 139 | render() { 140 | let { example } = this.state; 141 | return ( 142 | 143 | 144 | 145 | this.setState({ example: 1 })} 149 | > 150 | 151 | with Box 152 | 153 | 154 | 155 | this.setState({ example: 2 })} 159 | > 160 | 161 | without Box 162 | 163 | 164 | 165 | this.setState({ example: 3 })} 169 | > 170 | 171 | with Icon 172 | 173 | 174 | 175 | 176 | 177 | Animation: 178 | 179 | this.setState({ example: 4 })} 183 | > 184 | 185 | pulse 186 | 187 | 188 | 189 | this.setState({ example: 5 })} 193 | > 194 | 195 | zoomIn 196 | 197 | 198 | 199 | this.setState({ example: 6 })} 203 | > 204 | 205 | shake 206 | 207 | 208 | 209 | this.setState({ example: 7 })} 213 | > 214 | 215 | rotate 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | Selected your color: 224 | 225 | 226 | { this._renderRadioBtn() } 227 | 228 | 229 | { 230 | this.state.res && 231 | 232 | 233 | Selected Color: 234 | 235 | 236 | {this.state.res.label} 237 | 238 | 239 | } 240 | 241 | 242 | ); 243 | } 244 | }; 245 | 246 | const styles = StyleSheet.create({ 247 | types: { 248 | marginHorizontal: 5, 249 | borderWidth: 1, 250 | borderColor: '#bbb', 251 | padding: 4, 252 | borderRadius: 3, 253 | backgroundColor: '#fff' 254 | } 255 | }); 256 | 257 | export default App; 258 | -------------------------------------------------------------------------------- /example/rbrn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sramezani/radio-buttons-react-native/4e59c96c46a3131ed6cb77f137d3cdd27b4f8451/example/rbrn.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "radio-buttons-react-native", 3 | "version": "1.0.4", 4 | "description": "Animated radio buttons component for react native", 5 | "main": "RadioButtonRN.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/sramezani/radio-buttons-react-native.git" 12 | }, 13 | "keywords": [ 14 | "react-component", 15 | "react-native", 16 | "ios", 17 | "android", 18 | "form", 19 | "button", 20 | "radio-button", 21 | "radio-buttons", 22 | "react-native-radio-button", 23 | "animated", 24 | "react", 25 | "mobile" 26 | ], 27 | "author": "Siamak Ramezani ", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/sramezani/radio-buttons-react-native/issues" 31 | }, 32 | "homepage": "https://github.com/sramezani/radio-buttons-react-native#readme", 33 | "directories": { 34 | "example": "example" 35 | } 36 | } 37 | --------------------------------------------------------------------------------