UNPKG

hcmobile-sdk

Version:

mobile-sdk

200 lines (183 loc) 4.71 kB
import React, { Component } from 'react'; import { View, Text, StyleSheet, Animated, PanResponder, TouchableWithoutFeedback, ViewPropTypes } from 'react-native'; import PropTypes from 'prop-types'; export default class Switch extends Component { static propTypes = { onValueChange: PropTypes.func, disabled: PropTypes.bool, activeText: PropTypes.string, inActiveText: PropTypes.string, backgroundActive: PropTypes.string, backgroundInactive: PropTypes.string, value: PropTypes.bool, circleActiveColor: PropTypes.string, circleInActiveColor: PropTypes.string, circleSize: PropTypes.number, activeTextStyle: Text.propTypes.style, inactiveTextStyle: Text.propTypes.style, containerStyle: ViewPropTypes.style, barHeight: PropTypes.number, circleBorderWidth: PropTypes.number }; static defaultProps = { value: false, onValueChange: () => null, disabled: false, activeText: 'On', inActiveText: 'Off', backgroundActive: 'green', backgroundInactive: 'gray', circleActiveColor: 'white', circleInActiveColor: 'white', circleSize: 30, barHeight: null, circleBorderWidth: 1 }; constructor(props, context) { super(props, context); this.state = { value: props.value, transformSwitch: new Animated.Value(props.value ? props.circleSize / 2 : -props.circleSize / 2), backgroundColor: new Animated.Value(props.value ? 75 : -75), circleColor: new Animated.Value(props.value ? 75 : -75) }; this.handleSwitch = this.handleSwitch.bind(this); this.animateSwitch = this.animateSwitch.bind(this); } componentWillReceiveProps(nextProps) { const { disabled } = this.props; if (nextProps.value === this.props.value) { return; } if (disabled) { return; } this.animateSwitch(nextProps.value, () => { this.setState({ value: nextProps.value }); }); } handleSwitch() { const { value } = this.state; const { onValueChange, disabled } = this.props; if (disabled) { return; } this.setState({ value: !value }, () => onValueChange(this.state.value)); this.animateSwitch(!value, () => { }); } animateSwitch(value, cb = () => { }) { Animated.parallel([ Animated.spring(this.state.transformSwitch, { toValue: value ? this.props.circleSize / 2 : -this.props.circleSize / 2 }), Animated.timing(this.state.backgroundColor, { toValue: value ? 75 : -75, duration: 200 }), Animated.timing(this.state.circleColor, { toValue: value ? 75 : -75, duration: 200 }) ]).start(cb); } render() { const { transformSwitch, backgroundColor, circleColor, } = this.state; const { backgroundActive, backgroundInactive, circleActiveColor, circleInActiveColor, activeText, inActiveText, circleSize, containerStyle, activeTextStyle, inactiveTextStyle, barHeight, circleBorderWidth } = this.props; const interpolatedColorAnimation = backgroundColor.interpolate({ inputRange: [-75, 75], outputRange: [backgroundInactive, backgroundActive] }); const interpolatedCircleColor = circleColor.interpolate({ inputRange: [-75, 75], outputRange: [circleInActiveColor, circleActiveColor] }); return ( <TouchableWithoutFeedback onPress={this.handleSwitch} > <Animated.View style={[ styles.container, containerStyle, { backgroundColor: interpolatedColorAnimation, width: circleSize * 2, height: barHeight ? barHeight : circleSize, borderRadius: circleSize } ]} > <Animated.View style={[ styles.animatedContainer, { left: transformSwitch, width: circleSize * 2 }, ]} > <Text style={[styles.text, styles.paddingRight, activeTextStyle]}> {activeText} </Text> <Animated.View style={[styles.circle, { borderWidth: circleBorderWidth, backgroundColor: interpolatedCircleColor, width: circleSize, height: circleSize, borderRadius: circleSize / 2 }]} /> <Text style={[styles.text, styles.paddingLeft, inactiveTextStyle]}> {inActiveText} </Text> </Animated.View> </Animated.View> </TouchableWithoutFeedback> ); } } // 51 / 31 const styles = StyleSheet.create({ container: { width: 71, height: 30, borderRadius: 30, backgroundColor: 'black', // overflow: 'hidden' }, animatedContainer: { flex: 1, width: 78, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, circle: { width: 30, height: 30, borderRadius: 15, backgroundColor: 'white', borderColor: 'rgb(100, 100, 100)', }, text: { color: 'white', backgroundColor: 'transparent' }, paddingRight: { paddingRight: 5 }, paddingLeft: { paddingLeft: 5, } });