@@ -2,33 +2,36 @@ import React, { Component } from 'react'
22import PropTypes from "prop-types"
33import {
44 ViewPropTypes ,
5+ ColorPropType ,
56 StyleSheet ,
67 Animated ,
78 Easing ,
89 PanResponder ,
910 TouchableOpacity
1011} from 'react-native'
1112
13+ const SCALE = 6 / 5
14+
1215export default class extends Component {
1316 static propTypes = {
1417 width : PropTypes . number ,
1518 height : PropTypes . number ,
1619 value : PropTypes . bool ,
17- defaultValue : PropTypes . bool ,
1820 disabled : PropTypes . bool ,
19- circleColorActive : PropTypes . string ,
20- circleColorInactive : PropTypes . string ,
21- backgroundActive : PropTypes . string ,
22- backgroundInactive : PropTypes . string ,
21+ circleColorActive : ColorPropType ,
22+ circleColorInactive : ColorPropType ,
23+ backgroundActive : ColorPropType ,
24+ backgroundInactive : ColorPropType ,
2325 onAsyncPress : PropTypes . func ,
2426 onSyncPress : PropTypes . func ,
25- style : ViewPropTypes . style
27+ style : ViewPropTypes . style ,
28+ circleStyle : ViewPropTypes . style
2629 }
2730
2831 static defaultProps = {
2932 width : 40 ,
3033 height : 21 ,
31- defaultValue : false ,
34+ value : false ,
3235 disabled : false ,
3336 circleColorActive : 'white' ,
3437 circleColorInactive : 'white' ,
@@ -39,12 +42,11 @@ export default class extends Component {
3942
4043 constructor ( props , context ) {
4144 super ( props , context )
42- const { width, height } = props
45+ const { width, height, value } = props
4346
4447 this . offset = width - height + 1
4548 this . handlerSize = height - 2
46-
47- const value = props . value || props . defaultValue
49+
4850 this . state = {
4951 value,
5052 toggleable : true ,
@@ -55,12 +57,19 @@ export default class extends Component {
5557 }
5658
5759 componentWillReceiveProps ( nextProps ) {
58- const { value } = this . state
5960 if ( nextProps === this . props ) {
6061 return
6162 }
6263
63- if ( typeof nextProps . value !== 'undefined' && nextProps . value !== value ) {
64+ // componentWillReceiveProps will still be triggered if
65+ // render function of father component is triggered.
66+ // Thus, toggleSwitch will be executed without two-way bind.
67+ if ( typeof nextProps . value !== 'undefined' && nextProps . value !== this . props . value ) {
68+ /** you can add animation when changing value programmatically like following:
69+ /* this.animateHandler(this.handlerSize * SCALE, () => {
70+ /* this.toggleSwitch(true)
71+ /* })
72+ **/
6473 this . toggleSwitch ( true )
6574 }
6675 }
@@ -82,7 +91,7 @@ export default class extends Component {
8291 const { disabled } = this . props
8392 if ( disabled ) return
8493
85- this . animateHandler ( this . handlerSize * 6 / 5 )
94+ this . animateHandler ( this . handlerSize * SCALE )
8695 }
8796
8897 _onPanResponderMove = ( evt , gestureState ) => {
@@ -112,17 +121,18 @@ export default class extends Component {
112121 }
113122 }
114123
115- toggleSwitch = ( result , callback = ( ) => null ) => { // result of async
124+ toggleSwitch = ( result , callback = ( ) => null ) => { // " result" is result of task
116125 const { value, switchAnimation } = this . state
117126 const toValue = ! value
118127
119128 this . animateHandler ( this . handlerSize )
120129 if ( result ) {
121130 this . animateSwitch ( toValue , ( ) => {
122- callback ( toValue )
123131 this . setState ( {
124132 value : toValue ,
125133 alignItems : toValue ? 'flex-end' : 'flex-start'
134+ } , ( ) => {
135+ callback ( toValue )
126136 } )
127137 switchAnimation . setValue ( toValue ? - 1 : 1 )
128138 } )
@@ -158,6 +168,7 @@ export default class extends Component {
158168 const {
159169 backgroundActive, backgroundInactive,
160170 width, height, circleColorActive, circleColorInactive, style,
171+ circleStyle,
161172 ...rest
162173 } = this . props
163174
@@ -180,13 +191,13 @@ export default class extends Component {
180191 alignItems,
181192 borderRadius : height / 2 ,
182193 backgroundColor : interpolatedBackgroundColor } ] } >
183- < Animated . View style = { {
194+ < Animated . View style = { [ {
184195 backgroundColor : interpolatedCircleColor ,
185196 width : handlerAnimation ,
186197 height : this . handlerSize ,
187198 borderRadius : height / 2 ,
188199 transform : [ { translateX : switchAnimation } ]
189- } } />
200+ } , circleStyle ] } />
190201 </ Animated . View >
191202 )
192203 }
0 commit comments