1import React, {useEffect} from 'react'; 2import { 3 StyleSheet, 4 SwitchProps, 5 TouchableWithoutFeedback, 6 View, 7} from 'react-native'; 8import useColors from '@/hooks/useColors'; 9import rpx from '@/utils/rpx'; 10import Animated, { 11 useAnimatedStyle, 12 useSharedValue, 13 withTiming, 14} from 'react-native-reanimated'; 15import {timingConfig} from '@/constants/commonConst'; 16 17interface ISwitchProps extends SwitchProps {} 18const fixedWidth = rpx(40); 19 20export default function ThemeSwitch(props: ISwitchProps) { 21 const {value, onValueChange} = props; 22 const colors = useColors(); 23 24 const sharedValue = useSharedValue(value ? 1 : 0); 25 26 useEffect(() => { 27 sharedValue.value = withTiming( 28 value ? 1 : 0, 29 timingConfig.animationNormal, 30 ); 31 }, [value]); 32 33 const thumbStyle = useAnimatedStyle(() => { 34 return { 35 transform: [ 36 { 37 translateX: sharedValue.value * fixedWidth, 38 }, 39 ], 40 }; 41 }); 42 43 return ( 44 <TouchableWithoutFeedback 45 onPress={() => { 46 onValueChange?.(!value); 47 }}> 48 <View 49 style={[ 50 styles.container, 51 { 52 backgroundColor: value 53 ? colors.primary 54 : colors.textSecondary, 55 }, 56 props?.style, 57 ]}> 58 <Animated.View style={[styles.thumb, thumbStyle]} /> 59 </View> 60 </TouchableWithoutFeedback> 61 ); 62} 63 64const styles = StyleSheet.create({ 65 container: { 66 width: rpx(80), 67 height: rpx(40), 68 borderRadius: rpx(40), 69 justifyContent: 'center', 70 }, 71 thumb: { 72 width: rpx(34), 73 height: rpx(34), 74 borderRadius: rpx(17), 75 backgroundColor: 'white', 76 left: rpx(3), 77 }, 78}); 79