xref: /MusicFree/src/components/base/switch.tsx (revision 410a159129b1f6a7a1f44fde7bfad9a46f91e161)
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