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