├── README.md ├── SegmentedControl.js ├── SegmentedControlItem.js ├── package.json ├── screenshot_android1.png ├── screenshot_android2.png ├── screenshot_ios1.png └── screenshot_ios2.png /README.md: -------------------------------------------------------------------------------- 1 | # react-native-segmented-control 2 | react-native-segmentedControl for( Android / Ios ) 3 | 4 | 5 | ## Overview 6 | SegmentedControl using react-native,support android and ios. 7 | Pages won't be rendered when you switch to other tabs,also save the status of invisible pages. 8 | 9 | ## Installation 10 | 11 | First you need to install react-native-segmented-control: 12 | 13 | ```javascript 14 | npm install react-native-segmented-control --save 15 | ``` 16 | 17 | ## Props 18 | 19 | ### SegmentedControl 20 | 21 | | prop | value | required/optional | comment | 22 | | --- | --- | --- | --- | 23 | | defaultPage | number | optional | default:0 | 24 | | itemFontSize | number | optional | text fontsize default:14 | 25 | | itemButtonActiveColor | color | optional | ActiveButton color | 26 | | itemButtonColor | color | optional | defaultButton color | 27 | | itemTextActiveColor | color | optional | ActiveText color | 28 | | itemTextColor | color | optional | defaultText color | 29 | | itemButtonViewStyle | style | optional | button container style | 30 | | itemButtonBorderColor | color | optional | button border color | 31 | | itemHeaderViewStyle | style | optional | header container style | 32 | 33 | 34 | ### SegmentedControl.Item 35 | 36 | | prop | value | required/optional | comment | 37 | | --- | --- | --- | --- | 38 | | title | string | required | title of item | 39 | | onPress | function | optional | the function will be called when item is selected. | 40 | 41 | 42 | ## Usage 43 | 44 | ```javascript 45 | import SegmentedControl from 'react-native-segmented-control'; 46 | 47 | this.SegmentedControl=e} 56 | > 57 | 60 | page0 61 | 62 | 65 | page1 66 | 67 | 70 | page2 71 | 72 | 73 | 74 | ``` 75 | 76 | ###Methods 77 | * `update(number)` - select item. 78 | ```javascript 79 | this.SegmentedControl.update(number) 80 | ``` 81 | 82 | ## Screenshot 83 | 84 | # ios 85 | 86 | 87 | 88 | # android 89 | 90 | 91 | -------------------------------------------------------------------------------- /SegmentedControl.js: -------------------------------------------------------------------------------- 1 | import { 2 | StyleSheet, 3 | View, 4 | Image, 5 | Text, 6 | TouchableHighlight, 7 | Dimensions, 8 | TouchableOpacity, 9 | } from 'react-native'; 10 | import React, {Component} from 'react' 11 | 12 | import SegmentedControlItem from './SegmentedControlItem'; 13 | 14 | export default class SegmentedControl extends Component { 15 | static Item = SegmentedControlItem; 16 | 17 | static defaultProps = { 18 | defaultPage: 0, 19 | itemFontSize: 14, 20 | itemButtonActiveColor : '#5E89F7', 21 | itemButtonColor : '#fff', 22 | itemTextActiveColor : '#fff', 23 | itemTextColor : '#5E89F7', 24 | itemButtonViewStyle : undefined, 25 | itemButtonBorderColor : '#5E89F7', 26 | itemHeaderViewStyle : undefined, 27 | }; 28 | 29 | static propTypes = { 30 | ...View.propTypes, 31 | style: View.propTypes.style, 32 | defaultPage: React.PropTypes.number, 33 | itemFontSize: React.PropTypes.number, 34 | itemButtonActiveColor: React.PropTypes.string, 35 | itemButtonColor: React.PropTypes.string, 36 | itemTextActiveColor: React.PropTypes.string, 37 | itemTextColor: React.PropTypes.string, 38 | onItemSelected: React.PropTypes.func, 39 | itemButtonViewStyle : View.propTypes.style, 40 | itemButtonBorderColor: React.PropTypes.string, 41 | itemHeaderViewStyle : View.propTypes.style, 42 | }; 43 | 44 | constructor(props) { 45 | super(props); 46 | 47 | this.visibles = []; 48 | this.state = { 49 | selectedIndex: 0, 50 | } 51 | } 52 | 53 | render() { 54 | let children = this.props.children; 55 | let childrenLength = this.props.children.length; 56 | 57 | if (!childrenLength) { 58 | throw new Error(`SegmentedControlItem can not undefined`); 59 | } 60 | 61 | let navs = []; 62 | 63 | const contentViews = children.map((child,i) => { 64 | const buttonColor = this.state.selectedIndex == i ? this.props.itemButtonActiveColor : this.props.itemButtonColor; 65 | const textColor = this.state.selectedIndex == i ? this.props.itemTextActiveColor : this.props.itemTextColor; 66 | 67 | navs[i] = ( 68 | 0 ? {borderLeftWidth:0}:undefined, 74 | {backgroundColor:buttonColor}, 75 | i==0 ? {borderTopLeftRadius:5,borderBottomLeftRadius:5}:undefined, 76 | i==childrenLength-1 ? {borderTopRightRadius:5,borderBottomRightRadius:5}:undefined, 77 | {borderColor:this.props.itemButtonBorderColor} 78 | ]} 79 | onPress={() => { 80 | if (child.props.onPress) { 81 | child.props.onPress(); 82 | } 83 | this.update(i); 84 | }}> 85 | 92 | {child.props.title} 93 | 94 | 95 | ); 96 | 97 | if (!this.visibles[i]) { 98 | return null; 99 | } else { 100 | const style = this.state.selectedIndex === i ? styles.base : [styles.base,styles.gone]; 101 | return ( 102 | 106 | {child} 107 | 108 | ); 109 | } 110 | }); 111 | 112 | return ( 113 | 114 | 117 | 121 | {navs} 122 | 123 | 124 | 125 | 126 | {contentViews} 127 | 128 | 129 | ); 130 | } 131 | 132 | componentDidMount() { 133 | let page = this.props.defaultPage; 134 | 135 | if (page >= this.props.children.length || page < 0){ 136 | page = 0; 137 | } 138 | 139 | this.update(page); 140 | } 141 | 142 | update(index) { 143 | this.visibles[index] = true; 144 | this.setState({ 145 | selectedIndex: index, 146 | }); 147 | 148 | if (this.props.onItemSelected) { 149 | this.props.onItemSelected(index); 150 | } 151 | } 152 | } 153 | 154 | const styles = StyleSheet.create({ 155 | container: { 156 | flex: 1, 157 | width: Dimensions.get('window').width, 158 | overflow: 'hidden', 159 | }, 160 | content: { 161 | flex: 1, 162 | }, 163 | base: { 164 | position: 'absolute', 165 | overflow: 'hidden', 166 | left: 0, 167 | right: 0, 168 | top: 0, 169 | bottom: 0, 170 | }, 171 | gone: { 172 | // top: Dimensions.get('window').height, 173 | // bottom: -Dimensions.get('window').height, 174 | opacity: 0, 175 | }, 176 | nav: { 177 | flexDirection: 'row', 178 | width: Dimensions.get('window').width, 179 | borderTopWidth:1, 180 | borderColor:'#eaeaea', 181 | }, 182 | navItem: { 183 | flex: 1, 184 | paddingTop: 6, 185 | paddingBottom: 6, 186 | alignItems: 'center', 187 | }, 188 | center: { 189 | width: 56, 190 | alignItems: 'center', 191 | justifyContent: 'center', 192 | }, 193 | navImage: { 194 | width: 24, 195 | height: 24, 196 | marginBottom: 2, 197 | }, 198 | navImageChange: { 199 | top: -28, 200 | width: 56, 201 | height: 56, 202 | marginBottom: 2, 203 | position: 'absolute', 204 | borderRadius: 28, 205 | borderWidth: 3, 206 | borderColor: '#fff', 207 | alignSelf: 'center' 208 | }, 209 | navTextChange: { 210 | marginTop: 30, 211 | fontSize: 11, 212 | alignSelf: 'center' 213 | }, 214 | navText: { 215 | marginTop: 2, 216 | alignSelf: 'center', 217 | }, 218 | horizonLine: { 219 | backgroundColor: '#adadad', 220 | height: 1, 221 | width: Dimensions.get('window').width, 222 | }, 223 | badgeNoNumber: { 224 | flexDirection: 'row', 225 | justifyContent: 'center', 226 | top: -2, 227 | left: 36, 228 | position: 'absolute', 229 | width: 10, 230 | height: 10, 231 | borderRadius: 10, 232 | borderWidth: 1, 233 | alignItems: 'center', 234 | borderColor: '#ffffff', 235 | backgroundColor: '#ff0000', 236 | }, 237 | badgeWithNumber: { 238 | flexDirection: 'row', 239 | justifyContent: 'center', 240 | top: -4, 241 | left: 36, 242 | position: 'absolute', 243 | width: 20, 244 | height: 20, 245 | borderRadius: 10, 246 | borderWidth: 1, 247 | borderColor: '#ffffff', 248 | backgroundColor: '#ff0000', 249 | }, 250 | badgeText: { 251 | alignSelf: 'center', 252 | fontSize: 11, 253 | color: '#ffffff', 254 | backgroundColor: 'transparent', 255 | }, 256 | ItemView:{ 257 | flexDirection:'row', 258 | justifyContent:'center', 259 | alignSelf:'center', 260 | }, 261 | ItemButton:{ 262 | paddingHorizontal:10, 263 | paddingVertical:5, 264 | borderWidth:1, 265 | flex:1, 266 | alignItems:'center', 267 | }, 268 | ItemButtonText:{ 269 | 270 | }, 271 | }); 272 | -------------------------------------------------------------------------------- /SegmentedControlItem.js: -------------------------------------------------------------------------------- 1 | import { 2 | StyleSheet, 3 | View, 4 | Text, 5 | } from 'react-native'; 6 | import React, {Component} from 'react'; 7 | 8 | export default class SegmentedControlItem extends Component { 9 | 10 | render() { 11 | let child = this.props.children; 12 | 13 | if (child.length && child.length > 0) { 14 | throw new Error("onlyChild must be passed a children with exactly one child."); 15 | } 16 | 17 | return ( 18 | 19 | {child} 20 | 21 | ); 22 | } 23 | } 24 | 25 | const styles = StyleSheet.create({ 26 | weight: { 27 | flex: 1, 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-segmented-control", 3 | "version": "1.0.0", 4 | "description": "react-native-segmentedControl for( Android / Ios )", 5 | "main": "SegmentedControl.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/xuanheScript/react-native-segmented-control.git" 12 | }, 13 | "keywords": [ 14 | "lijie123" 15 | ], 16 | "author": "", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/xuanheScript/react-native-segmented-control/issues" 20 | }, 21 | "homepage": "https://github.com/xuanheScript/react-native-segmented-control#readme" 22 | } 23 | -------------------------------------------------------------------------------- /screenshot_android1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuanheScript/react-native-segmented-control/8a12f9fe602c754741eeb8aba5f06420b19a3758/screenshot_android1.png -------------------------------------------------------------------------------- /screenshot_android2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuanheScript/react-native-segmented-control/8a12f9fe602c754741eeb8aba5f06420b19a3758/screenshot_android2.png -------------------------------------------------------------------------------- /screenshot_ios1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuanheScript/react-native-segmented-control/8a12f9fe602c754741eeb8aba5f06420b19a3758/screenshot_ios1.png -------------------------------------------------------------------------------- /screenshot_ios2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuanheScript/react-native-segmented-control/8a12f9fe602c754741eeb8aba5f06420b19a3758/screenshot_ios2.png --------------------------------------------------------------------------------