Hey, I've translated your code to TypeScript and simplified it in the process.
I've also added a couple of extra Props: fontFamily, fontSize, switchMargin which was hardcoded to 6, btnBorderWidth which was hardcoded to 1 and btnBorderRadius which was hardcoded to switchBorderRadius.
Feel free to test it and/or merge it into your repo.
Thanks for your work!
import React, { Component } from "react";
import {
View,
Text,
TouchableWithoutFeedback,
StyleSheet,
Animated,
} from "react-native";
type Props = {
onValueChange: (activeSwitch: 1 | 2) => void;
fontFamily?: string;
fontSize?: number;
} & typeof SwitchButton.defaultProps;
interface State {
offsetX: Animated.Value;
}
class SwitchButton extends Component<Props, State> {
static defaultProps = {
text1: "ON",
text2: "OFF",
activeSwitch: 1 as 1 | 2,
switchWidth: 100,
switchHeight: 44,
switchMargin: 6,
switchBorderRadius: 22,
switchBorderColor: "#d4d4d4",
switchBackgroundColor: "#fff",
switchBorderWidth: 1,
changeSpeed: 100,
fontColor: "#b1b1b1",
activeFontColor: "#fff",
btnBorderColor: "#00a4b9",
btnBorderWidth: 1,
btnBorderRadius: 22,
btnBackgroundColor: "#00bcd4",
direction: "ltr" as "ltr" | "rtl",
};
constructor(props: Props) {
super(props);
this.state = {
offsetX: new Animated.Value(
this.props.activeSwitch === 1
? this.getOffsetXFor1()
: this.getOffsetXFor2()
),
};
}
componentWillReceiveProps = (nextProps: Props) => {
if (this.props.activeSwitch !== nextProps.activeSwitch) {
this.animate();
}
};
getOffsetXFor1 = () => {
return this.props.switchMargin;
};
getOffsetXFor2 = () => {
const { switchWidth, switchMargin, direction } = this.props;
let dirsign = 1;
if (direction === "rtl") {
dirsign = -1;
}
return (switchWidth / 2 + switchMargin) * dirsign;
};
switchThump = () => {
const { onValueChange } = this.props;
if (this.props.activeSwitch === 1) {
onValueChange(2);
} else {
onValueChange(1);
}
};
animate = () => {
const { activeSwitch, changeSpeed } = this.props;
if (activeSwitch === 1) {
Animated.timing(this.state.offsetX, {
toValue: this.getOffsetXFor2(),
duration: changeSpeed,
}).start();
} else {
Animated.timing(this.state.offsetX, {
toValue: this.getOffsetXFor1(),
duration: changeSpeed,
}).start();
}
};
render = () => (
<TouchableWithoutFeedback onPress={this.switchThump}>
<View
style={{
width: this.props.switchWidth,
height: this.props.switchHeight,
borderRadius: this.props.switchBorderRadius,
borderWidth: this.props.switchBorderWidth,
borderColor: this.props.switchBorderColor,
backgroundColor: this.props.switchBackgroundColor,
}}
>
<View
style={
this.props.direction === "ltr" ? switchStyles.ltr : switchStyles.rtl
}
>
<Animated.View
style={{
transform: [{ translateX: this.state.offsetX }],
top: this.props.switchMargin,
}}
>
<View
style={{
width: this.props.switchWidth / 2 - 2 * this.props.switchMargin,
height: this.props.switchHeight - 2 * this.props.switchMargin,
borderWidth: this.props.btnBorderWidth,
borderRadius: this.props.btnBorderRadius,
borderColor: this.props.btnBorderColor,
backgroundColor: this.props.btnBackgroundColor,
}}
/>
</Animated.View>
<View
style={[
switchStyles.textPos,
{
width: this.props.switchWidth / 2,
height: this.props.switchHeight,
left: 0,
},
]}
>
<Text
style={{
fontFamily: this.props.fontFamily,
fontSize: this.props.fontSize,
textAlign: "center",
color:
this.props.activeSwitch === 1
? this.props.activeFontColor
: this.props.fontColor,
}}
>
{this.props.text1}
</Text>
</View>
<View
style={[
switchStyles.textPos,
{
width: this.props.switchWidth / 2,
height: this.props.switchHeight,
right: 0,
},
]}
>
<Text
style={{
fontFamily: this.props.fontFamily,
fontSize: this.props.fontSize,
textAlign: "center",
color:
this.props.activeSwitch === 2
? this.props.activeFontColor
: this.props.fontColor,
}}
>
{this.props.text2}
</Text>
</View>
</View>
</View>
</TouchableWithoutFeedback>
);
}
const switchStyles = StyleSheet.create({
textPos: {
position: "absolute",
justifyContent: "center",
alignItems: "center",
},
rtl: {
flexDirection: "row-reverse",
},
ltr: {
flexDirection: "row",
},
});
export default SwitchButton;
Hey, I've translated your code to TypeScript and simplified it in the process.
I've also added a couple of extra Props: fontFamily, fontSize, switchMargin which was hardcoded to 6, btnBorderWidth which was hardcoded to 1 and btnBorderRadius which was hardcoded to switchBorderRadius.
Feel free to test it and/or merge it into your repo.
Thanks for your work!