-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathKeyboardAvoidingView.tsx
46 lines (41 loc) · 1.39 KB
/
KeyboardAvoidingView.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { useCallback } from 'react';
import type { LayoutChangeEvent, LayoutRectangle } from 'react-native';
import { Platform, useWindowDimensions, type ViewStyle } from 'react-native';
import Animated, {
useAnimatedKeyboard,
useAnimatedStyle,
useSharedValue
} from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export const KeyboardAvoidingView: React.FC<
React.PropsWithChildren<{ style: ViewStyle }>
> = ({ children, style }) => {
const keyboard = useAnimatedKeyboard({
isStatusBarTranslucentAndroid: true
});
const currentFrame = useSharedValue<LayoutRectangle | null>(null);
const { height: screenHeight } = useWindowDimensions();
const safeAreaInsets = useSafeAreaInsets();
const topPadding = Platform.OS === 'android' ? safeAreaInsets.top : 0;
const onLayout = useCallback(
(event: LayoutChangeEvent) => {
currentFrame.value = event.nativeEvent.layout;
},
[currentFrame]
);
const animatedStyles = useAnimatedStyle(() => {
if (!currentFrame.value) return {};
const translateY = -Math.max(
currentFrame.value.y +
currentFrame.value.height -
(screenHeight + topPadding - keyboard.height.value),
0
);
return { transform: [{ translateY }] };
});
return (
<Animated.View onLayout={onLayout} style={[style, animatedStyles]}>
{children}
</Animated.View>
);
};