import React, {Component} from 'react'; import { Animated, StyleProp, View, ViewProps, ViewStyle, } from 'react-native'; import MKColor from '../MKColor'; export type ThumbProps = { checked: boolean, onColor?: string, offColor?: string, rippleColor?: string, rippleAniDuration: number, rippleRadius: number, thumbStyle?: StyleProp, } & ViewProps; interface ThumbState { checked: boolean } // ##
Thumb
// `Thumb` component of the [`Switch`](#switch). // Which is displayed as a circle with shadow and ripple effect. export class Thumb extends Component { // Default props of `Thumb` static defaultProps: ThumbProps = { checked: false, pointerEvents: 'none', rippleAniDuration: 250, rippleRadius: 14, style: { elevation: 2, shadowColor: 'black', shadowOffset: { height: 1, width: 0, }, shadowOpacity: 0.7, shadowRadius: 1, }, }; private animatedRippleScale = new Animated.Value(0); private animatedRippleAlpha = new Animated.Value(0); private rippleAni?: Animated.CompositeAnimation; private pendingRippleAni?: () => void; // pending animation process, if any constructor(props: ThumbProps) { super(props); this.state = { checked: props.checked, }; } // componentWillMount() { // this.setState({checked: this.props.checked}); // } componentWillReceiveProps(nextProps: ThumbProps) { if (nextProps.checked !== this.state.checked) { this.setState({checked: nextProps.checked}); } } // When a toggle action started. startToggle() { this.showRipple(); } // When a toggle action is finished (confirmed or canceled). endToggle() { this.hideRipple(); } // When a toggle action (from the given state) is confirmed. // - {`boolean`} `fromState` the previous state confirmToggle(fromState: boolean) { this.setState({checked: !fromState}); } // Start the ripple effect showRipple() { // scaling up the ripple layer this.rippleAni = Animated.parallel([ Animated.timing(this.animatedRippleAlpha, { duration: this.props.rippleAniDuration, toValue: 1, }), Animated.timing(this.animatedRippleScale, { duration: this.props.rippleAniDuration, toValue: 1, }), ]); this.rippleAni.start(() => { this.rippleAni = undefined; // if any pending animation, do it if (this.pendingRippleAni) { this.pendingRippleAni(); } }); } // Stop the ripple effect hideRipple() { this.pendingRippleAni = () => { Animated.parallel([ Animated.timing(this.animatedRippleScale, { duration: this.props.rippleAniDuration || 250, toValue: 0, }), Animated.timing(this.animatedRippleAlpha, { duration: this.props.rippleAniDuration || 250, toValue: 0, }), ]).start(); this.pendingRippleAni = undefined; }; if (!this.rippleAni) { // previous ripple animation is done, good to go this.pendingRippleAni(); } } // Rendering the `Thumb` render() { const rippleSize = this.props.rippleRadius * 2; return ( ); } } // Enable animations on `Thumb` const AnimatedThumb = Animated.createAnimatedComponent(Thumb); export default AnimatedThumb