解决此种问题的方式有很多
-
可以导入原生库
react-native-switch
-
切图 (会缺少动画)
-
使用 js 组件

这里使用 js 绘制组件(原生体验)解决此类问题
Switch.tsx
tsx
import React, { useEffect, useRef, useState } from 'react';
import { Animated, Pressable, StyleSheet } from 'react-native';
interface SwitchProps {
value?: boolean;
onChange?: (value: boolean) => void;
}
const Switch: React.FC<SwitchProps> = ({ value = false, onChange }) => {
const switchAnim = useRef(new Animated.Value(0)).current;
const switchHandle = () => {
onChange?.(!value);
};
useEffect(() => {
const toValue = value ? 23 : 3;
Animated.timing(switchAnim, {
toValue,
duration: 100,
useNativeDriver: false, // 此处原生驱动会导致 ios 颜色显示不对
}).start();
}, [switchAnim, value]);
const backgroundColor = switchAnim.interpolate({
inputRange: [0, 25],
outputRange: ['#D2D2D2', '#904FF5'],
});
return (
<Pressable onPress={switchHandle}>
<Animated.View style={[styles.radioContainer, { backgroundColor }]}>
<Animated.View style={[styles.radio, { transform: [{ translateX: switchAnim }] }]} />
</Animated.View>
</Pressable>
);
};
const styles = StyleSheet.create({
radioContainer: {
width: 52,
height: 32,
borderRadius: 17,
justifyContent: 'center',
marginRight: 5,
},
radio: {
width: 25,
height: 25,
backgroundColor: '#FFFFFF',
borderRadius: 15,
},
});
export default (props: SwitchProps) => {
const [value, setValue] = useState(props.value || false);
// 监听 props.value 的变化并更新内部状态
useEffect(() => {
setValue(props.value ?? false);
}, [props.value]);
return (
<Switch
value={value}
onChange={() => {
props.onChange?.(!value);
}}
/>
);
};
用法
tsx
<Switch value={value} onChange={(value: boolean)=>{}} />