Skip to content

Commit 7778f11

Browse files
committed
add onAnimationEnd function
1 parent 3fc70ff commit 7778f11

6 files changed

Lines changed: 63 additions & 23 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ const styles = StyleSheet.create({
6868
| width | number | 100 |
6969
| value | boolean | false |
7070
| onValueChange | function | undefined |
71+
| onAnimationEnd | function | undefined |
7172
| disabled | boolean | false |
7273
| activeText | string | ON |
7374
| inActiveText | string | OFF |

example/ios/SwitchExample.xcodeproj/xcshareddata/xcschemes/SwitchExample.xcscheme

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
33
LastUpgradeVersion = "1210"
4-
version = "1.3">
4+
version = "1.7">
55
<BuildAction
66
parallelizeBuildables = "YES"
77
buildImplicitDependencies = "YES">
@@ -22,6 +22,13 @@
2222
</BuildActionEntry>
2323
</BuildActionEntries>
2424
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES"
30+
shouldAutocreateTestPlan = "YES">
31+
</TestAction>
2532
<LaunchAction
2633
buildConfiguration = "Debug"
2734
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"

example/src/App.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,15 @@ export default function App() {
1010
3: true,
1111
});
1212

13+
const [theme, setTheme] = React.useState('light');
14+
1315
return (
14-
<View style={styles.container}>
16+
<View
17+
style={[
18+
styles.container,
19+
{ backgroundColor: theme === 'dark' ? '#666' : '#ccc' },
20+
]}
21+
>
1522
<View>
1623
<Switch
1724
value={value['0']}
@@ -21,6 +28,7 @@ export default function App() {
2128
inActiveText="حرام"
2229
backgroundInActive={'#ff0000'}
2330
circleInActiveColor={'#fff'}
31+
disabled={false}
2432
circleSize={25}
2533
/>
2634
</View>
@@ -34,7 +42,7 @@ export default function App() {
3442
switchBorderRadius={30}
3543
switchPaddingLeft={2}
3644
switchPaddingRight={2}
37-
circleInActiveColor='#ff5454'
45+
circleInActiveColor="#ff5454"
3846
switchStyle={{ paddingVertical: 4 }}
3947
/>
4048
</View>
@@ -76,6 +84,10 @@ export default function App() {
7684
/>
7785
</View>
7886
}
87+
onAnimationEnd={(_value) => {
88+
setTheme(!_value ? 'dark' : 'light');
89+
console.log('theme is ', !_value ? 'dark' : 'light');
90+
}}
7991
/>
8092
</View>
8193
</View>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@meksiabdou/react-native-switch",
3-
"version": "1.0.6",
3+
"version": "1.0.7",
44
"description": "Customisable switch component for React Native",
55
"main": "lib/commonjs/index",
66
"module": "lib/module/index",

src/components/switch.tsx

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,22 @@ import {
33
StyleSheet,
44
TouchableWithoutFeedback,
55
I18nManager,
6-
View,
76
} from 'react-native';
87
import Reanimated, {
8+
AnimationCallback,
99
useAnimatedStyle,
1010
useSharedValue,
1111
withSpring,
12+
runOnJS,
1213
} from 'react-native-reanimated';
1314
import type { SwitchProps } from '../types';
1415

15-
const spring = (_value: any, config: any = { damping: 20, stiffness: 120 }) =>
16-
withSpring(_value, config);
16+
const spring = (
17+
_value: any,
18+
config: any = { damping: 20, stiffness: 120 },
19+
callback?: AnimationCallback
20+
) =>
21+
withSpring(_value, config, callback);
1722

1823
const PADDINGHORIZONTAL = 2;
1924

@@ -45,6 +50,7 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
4550
switchStyle,
4651
circleChildrenActive,
4752
circleChildrenInActive,
53+
onAnimationEnd,
4854
} = IProps;
4955

5056
const { isRTL } = I18nManager;
@@ -142,7 +148,6 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
142148
(defaultCircleSize +
143149
(defaultPadding.paddingLeft + defaultPadding.paddingRight)));
144150
if (value) {
145-
circleTranslateX.value = spring(size, { damping: 15, stiffness: 120 });
146151
textTranslateXActive.value = spring(0);
147152
textTranslateXInActive.value = spring(factory * defaultWidth);
148153
if (circleActiveColor) {
@@ -153,8 +158,17 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
153158
}
154159
circleChildrenActiveOpacity.value = spring(1);
155160
circleChildrenInActiveOpacity.value = spring(0);
161+
circleTranslateX.value = spring(
162+
size,
163+
{ damping: 15, stiffness: 120 },
164+
(finished?: boolean) => {
165+
'worklet';
166+
if (finished && onAnimationEnd) {
167+
runOnJS(onAnimationEnd)(true);
168+
}
169+
}
170+
);
156171
} else {
157-
circleTranslateX.value = spring(0, { damping: 15, stiffness: 120 });
158172
textTranslateXActive.value = spring(-(defaultWidth * factory));
159173
textTranslateXInActive.value = spring(0);
160174
if (circleInActiveColor) {
@@ -165,6 +179,16 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
165179
}
166180
circleChildrenActiveOpacity.value = spring(0);
167181
circleChildrenInActiveOpacity.value = spring(1);
182+
circleTranslateX.value = spring(
183+
0,
184+
{ damping: 15, stiffness: 120 },
185+
(finished?: boolean) => {
186+
'worklet';
187+
if (finished && onAnimationEnd) {
188+
runOnJS(onAnimationEnd)(false);
189+
}
190+
}
191+
);
168192
}
169193
}, [value, defaultWidth, defaultCircleSize, defaultPadding, isRTL]);
170194

@@ -176,20 +200,14 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
176200
}
177201
}, [disabled]);
178202

179-
const Button = (props: any) => {
180-
if (typeof onValueChange === 'function' && !disabled) {
181-
return (
182-
<TouchableWithoutFeedback
183-
{...props}
184-
onPress={() => onValueChange(!value)}
185-
/>
186-
);
187-
}
188-
return <View {...props} />;
189-
};
190-
191203
return (
192-
<Button>
204+
<TouchableWithoutFeedback
205+
onPress={() => {
206+
if (!disabled) {
207+
onValueChange?.(!value);
208+
}
209+
}}
210+
>
193211
<Reanimated.View
194212
style={[
195213
styles.switch,
@@ -277,14 +295,15 @@ const Switch = (IProps: SwitchProps): JSX.Element => {
277295
</Reanimated.View>
278296
</Reanimated.View>
279297
</Reanimated.View>
280-
</Button>
298+
</TouchableWithoutFeedback>
281299
);
282300
};
283301

284302
Switch.defaultProps = {
285303
disabled: false,
286304
value: false,
287305
onValueChange: undefined,
306+
onAnimationEnd: undefined,
288307
activeText: 'ON',
289308
inActiveText: 'OFF',
290309
backgroundActive: '#249c00',

src/types/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export interface SwitchProps {
55
disabled?: boolean;
66
value: boolean;
77
onValueChange?: (value: boolean) => void;
8+
onAnimationEnd?: (value?: boolean) => void;
89
width?: number;
910
activeText?: string;
1011
inActiveText?: string;

0 commit comments

Comments
 (0)