@ahsankk/react-native-animated-components
Version:
A set of reusable animated components for React Native using Reanimated
64 lines (63 loc) • 2.11 kB
JavaScript
import React, { useEffect, useState } from 'react';
import { View, Pressable, StyleSheet, } from 'react-native';
import Animated, { useSharedValue, withTiming, useAnimatedStyle, } from 'react-native-reanimated';
const Switch = ({ value = false, onChange, circleStyle, switchTrackStyle, labelStyle, labels = { on: 'ON', off: 'OFF' } }) => {
const [isOn, setIsOn] = useState(value);
const translateX = useSharedValue(isOn ? 32 : 2);
const toggleSwitch = () => {
const newValue = !isOn;
setIsOn(newValue);
translateX.value = withTiming(newValue ? 32 : 2, { duration: 300 });
};
const circleAnimatedStyle = useAnimatedStyle(() => ({
transform: [{ translateX: translateX.value }],
}));
const textAnimatedStyle = useAnimatedStyle(() => ({
transform: [{ translateX: translateX.value === 32 ? 2 : 32 }],
}));
useEffect(() => {
onChange(isOn);
}, [isOn]);
return (<Pressable onPress={toggleSwitch} style={styles.container}>
<View style={[styles.switchTrack, switchTrackStyle]}>
<Animated.Text style={[styles.switchText, textAnimatedStyle, labelStyle]}>
{isOn ? labels.on : labels.off}
</Animated.Text>
<Animated.View style={[styles.circle, circleAnimatedStyle, circleStyle]}/>
</View>
</Pressable>);
};
const styles = StyleSheet.create({
container: {
padding: 10,
},
switchTrack: {
width: 70,
height: 32,
backgroundColor: '#ccc',
borderRadius: 16,
justifyContent: 'center',
position: 'relative',
overflow: 'hidden',
},
switchText: {
position: 'absolute',
fontWeight: 'bold',
color: '#333',
zIndex: 1,
fontSize: 12,
marginHorizontal: 5,
},
circle: {
width: 28,
height: 28,
backgroundColor: '#fff',
borderRadius: 14,
position: 'absolute',
top: 2,
left: 2,
zIndex: 2,
elevation: 2,
},
});
export default Switch;