React Native之(支持iOS與Android)自定義單選按鈕(RadioGroup,RadioButton)
一,需求與簡單介紹
在開發項目時發現RN沒有給提供RadioButton和RadioGroup這兩個組件,只有CheckBox組件(不支持iOS),但是項目中確實有有一些地方需要使用到RadioButton和RadioGroup,比如默認地址的選擇等。
需求:
- 可以指定選中狀態和未選中狀態的顏色。
- 可以指定該單選按鈕是否可選:disabled。
- 可以指定整體的樣式,就像使用系統組件一樣,這個用style來接收。
- 可以自定義寬(width)高(height)。
二,RadioButton(如需完整的代碼,請留言評論)
在RN中控制一個View動態改變需要使用到state,這里定義一個state變量selected來記錄RadioButton是否被選中,並且可以默認選中某一個,為true為選中狀態,false為未選中狀態:(如需完整的代碼,請留言評論)
1 this.setState({ 2 selectedIndex: nextProps.selectedIndex//從RadioGroup組件傳入 3 })
state變量和動態控制一個組件的改變,但是組件改變之前仍然可能會顯示一些東西,這些東西用props來控制,而且可以用這些props定義一些默認的屬性,例如我們可以定義默認的顏色等:
1 RadioGroup.defaultProps = { 2 size: defaultSize, 3 thickness: defaultThickness, 4 color: defaultColor, 5 highlightColor: null, 6 }
在使用時我們可能會給這個RadioButton添加style屬性,例如單選按鈕的寬,高顏色等,以及選中的小圓點顏色,寬,高等等等,這個是在外面設置的,在內部我們同樣會設置style屬性
1 getRadioStyle(){ 2 return { 3 height: this.context.size, 4 width: this.context.size, 5 borderRadius: this.context.size / 2, 6 borderWidth: this.context.thickness, 7 borderColor: this.props.isSelected && this.props.activeColor?this.props.activeColor:this.context.color, 8 } 9 } 10 11 getRadioDotStyle(){ 12 return { 13 height: this.context.size / 2, 14 width: this.context.size / 2, 15 borderRadius: this.context.size / 4, 16 backgroundColor: this.props.color || this.props.activeColor, 17 } 18 }
給最外層的View添加TouchableWithoutFeedback組件,添加點擊事件以及是否可點擊狀態:
1 <View style={{opacity: this.props.disabled?0.4:1}}> 2 <TouchableWithoutFeedback 3 disabled={this.props.disabled}//是否可點擊 4 onPress={() => this.context.onSelect(this.props.index, this.props.value)}//選中事件 5 > 6 {children} 7 </TouchableWithoutFeedback> 8 </View>
選中之后的樣式選擇:(如需完整的代碼,請留言評論)
1 isSelected(){ 2 if(this.props.isSelected) 3 return <View style={this.getRadioDotStyle()}/> 4 }
三,RadioGroup(如需完整的代碼,請留言評論)
使用RadioButton大部分情況是多個共同使用,而且只能有一個被選中,android中就有這樣的組件,但是在RN中沒有找到,其實這個也很容易實現,原理是通過RadioGroup來生成多個RadioButton並且持有這些RadioButton的引用,當一個被選中的時候把其他的置為不選中(如需完整的代碼,請留言評論)。
1 if(nextProps.selectedIndex != this.prevSelected){ 2 this.prevSelected = nextProps.selectedIndex 3 this.setState({ 4 selectedIndex: nextProps.selectedIndex 5 }) 6 }
使用RadioGroup時給這個RadioButton傳遞多個即可,然后RadioGroup通過數組來創建RadioGroup,因為同樣要指定RadioButton的樣式,所以在外部使用時直接把style的各種樣式和屬性一並傳遞給RadioGroup,RadioGroup在創建RadioButton時把這些樣式屬性再傳遞給RadioButton(如需完整的代碼,請留言評論):
1 <View style={this.props.style}> 2 {radioButtons} 3 </View> 4 RadioGroup.childContextTypes = { 5 onSelect: PropTypes.func.isRequired, 6 size: PropTypes.number.isRequired, 7 thickness: PropTypes.number.isRequired, 8 color: PropTypes.string.isRequired, 9 activeColor: PropTypes.string, 10 highlightColor: PropTypes.string, 11 }
獲取選中事件的函數(如需完整的代碼,請留言評論):
1 onSelect(index, value){ 2 this.setState({ 3 selectedIndex: index 4 }) 5 if(this.props.onSelect) 6 this.props.onSelect(index, value) 7 }
四,使用實例(如需完整的代碼,請留言評論)
已實現的樣列(如需完整的代碼,請留言評論):

組件代碼實現:
1 <RadioGroup 2 style={{ backgroundColor: '#fff' }} 3 onSelect={(index, value) => this.onSelect(index, value)} 4 selectedIndex={this.state.selectedIndex} 5 > 6 {UsersAddress.map((model, i) => { 7 8 return ( 9 <RadioButton 10 key={i} 11 value={model} 12 selectedIndex={1} 13 style={{ backgroundColor: '#fff', marginBottom: 12, borderBottomColor: '#e4e4e4', borderBottomWidth: 12 }}> 14 <Text>張三</Text> 15 </RadioButton> 16 <RadioButton 17 key={i} 18 value={model} 19 selectedIndex={1} 20 style={{ backgroundColor: '#fff', marginBottom: 12, borderBottomColor: '#e4e4e4', borderBottomWidth: 12 }}> 21 <Text>李四</Text> 22 </RadioButton> 23 <RadioButton 24 key={i} 25 value={model} 26 selectedIndex={1} 27 style={{ backgroundColor: '#fff', marginBottom: 12, borderBottomColor: '#e4e4e4', borderBottomWidth: 12 }}> 28 <Text>王二</Text> 29 </RadioButton> 30 </RadioGroup>
1 onSelect(index, value) { 2 //alert(JSON.stringify(value)) 3 //this.openAduice() 4 this.setState({ 5 text: `Selected index: ${index} , value: ${value}`, 6 addressId: value.id 7 }) 8 }
(如需完整的代碼,請留言評論,留下聯系方式)
