Skip to content

Commit 537b566

Browse files
committed
improve route change animation
1 parent d521779 commit 537b566

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

src/hooks/use-router.ts

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {createContext, useCallback, useContext, useState} from 'react';
2+
import {Animated} from 'react-native';
23
import {ActionSheetRef} from './../index';
34
export type Route = {
45
/**
@@ -56,23 +57,39 @@ export const useRouter = ({
5657
initialRoute,
5758
routes,
5859
getRef,
60+
routeOpacity,
5961
}: {
6062
initialRoute?: string;
6163
routes?: Route[];
6264
getRef?: () => ActionSheetRef;
6365
onNavigate?: (route: string) => void;
6466
onNavigateBack?: (route: string) => void;
67+
routeOpacity: Animated.Value;
6568
}): Router => {
6669
const [stack, setStack] = useState<Route[]>([]);
6770
const currentRoute: Route | undefined = stack?.[stack.length - 1];
6871

72+
const animate = useCallback(
73+
(snap = 0, opacity = 0, delay = 0) => {
74+
getRef?.().snapToRelativeOffset(snap);
75+
Animated.timing(routeOpacity, {
76+
toValue: opacity,
77+
duration: 150,
78+
useNativeDriver: true,
79+
delay: delay,
80+
}).start();
81+
},
82+
[getRef, routeOpacity],
83+
);
84+
6985
const navigate = useCallback(
7086
(name: string, params?: any, snap?: number) => {
71-
getRef?.().snapToRelativeOffset(snap || 20);
87+
animate(snap || 20, 0);
7288
setTimeout(() => {
7389
setStack(state => {
7490
const next = routes?.find(route => route.name === name);
7591
if (!next) {
92+
animate(0, 1);
7693
return state;
7794
}
7895
const currentIndex = state.findIndex(
@@ -84,14 +101,12 @@ export const useRouter = ({
84101
return [...nextStack, {...next, params: params || next.params}];
85102
}
86103
onNavigate?.(next.name);
87-
setTimeout(() => {
88-
getRef?.().snapToRelativeOffset(0);
89-
}, 1);
104+
animate(0, 1, 150);
90105
return [...state, next];
91106
});
92-
}, 300);
107+
}, 100);
93108
},
94-
[getRef, onNavigate, routes],
109+
[animate, routes, onNavigate],
95110
);
96111

97112
const initialNavigation = () => {
@@ -104,37 +119,47 @@ export const useRouter = ({
104119
} else {
105120
setStack([routes[0]]);
106121
}
122+
Animated.timing(routeOpacity, {
123+
toValue: 1,
124+
duration: 150,
125+
useNativeDriver: true,
126+
}).start();
107127
};
108128

109129
const goBack = (name?: string, snap?: number) => {
110130
getRef?.().snapToRelativeOffset(snap || -10);
131+
animate(snap || -10, 0);
111132
setTimeout(() => {
112133
setStack(state => {
113134
const next = routes?.find(route => route.name === name);
114135
if (state.length === 1) {
115136
close();
137+
animate(0, 1);
116138
return state;
117139
}
118140

119141
if (!next) {
120142
const nextStack = [...state];
121143
nextStack.pop();
122144
if (currentRoute) {
123-
getRef?.()?.snapToRelativeOffset(0);
124145
onNavigateBack?.(nextStack[nextStack.length - 1]?.name);
146+
animate(0, 1, 150);
125147
}
126148
return nextStack;
127149
}
128150
const currentIndex = stack.findIndex(route => route.name === next.name);
129151
if (currentIndex > -1) {
130152
const nextStack = [...state];
131153
nextStack.splice(currentIndex);
154+
onNavigateBack?.(nextStack[nextStack.length - 1]?.name);
155+
animate(0, 1, 150);
132156
return [...nextStack, next];
133157
}
158+
animate(0, 1, 150);
134159
onNavigateBack?.(next.name);
135160
return [...stack, next];
136161
});
137-
}, 150);
162+
}, 100);
138163
};
139164

140165
const close = () => {

src/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ export default forwardRef<ActionSheetRef, ActionSheetProps>(
180180
translateY: new Animated.Value(0),
181181
underlayTranslateY: new Animated.Value(100),
182182
keyboardTranslate: new Animated.Value(0),
183+
routeOpacity: new Animated.Value(0),
183184
});
184185

185186
const router = useRouter({
@@ -188,6 +189,7 @@ export default forwardRef<ActionSheetRef, ActionSheetProps>(
188189
initialRoute: initialRoute,
189190
onNavigate: props.onNavigate,
190191
onNavigateBack: props.onNavigateBack,
192+
routeOpacity: animations.routeOpacity,
191193
});
192194
const routerRef = useRef(router);
193195
useEffect(() => {
@@ -1121,13 +1123,14 @@ export default forwardRef<ActionSheetRef, ActionSheetProps>(
11211123
{router?.stack.map(route => {
11221124
const RouteComponent = route.component as any;
11231125
return (
1124-
<View
1126+
<Animated.View
11251127
key={route.name}
11261128
style={{
11271129
display:
11281130
route.name !== router.currentRoute?.name
11291131
? 'none'
11301132
: 'flex',
1133+
opacity: animations.routeOpacity,
11311134
}}>
11321135
<RouterParamsContext.Provider
11331136
value={route?.params}>
@@ -1137,7 +1140,7 @@ export default forwardRef<ActionSheetRef, ActionSheetProps>(
11371140
payload={payloadRef.current}
11381141
/>
11391142
</RouterParamsContext.Provider>
1140-
</View>
1143+
</Animated.View>
11411144
);
11421145
})}
11431146
</RouterContext.Provider>

0 commit comments

Comments
 (0)