xref: /MusicFree/src/components/base/switch.tsx (revision 8e47be56b0121ae1a9c00382d70902276ffca225)
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                ]}>
57                <Animated.View style={[styles.thumb, thumbStyle]} />
58            </View>
59        </TouchableWithoutFeedback>
60    );
61}
62
63const styles = StyleSheet.create({
64    container: {
65        width: rpx(80),
66        height: rpx(40),
67        borderRadius: rpx(40),
68        justifyContent: 'center',
69    },
70    thumb: {
71        width: rpx(34),
72        height: rpx(34),
73        borderRadius: rpx(17),
74        backgroundColor: 'white',
75        left: rpx(3),
76    },
77});
78