|
1 | 1 | import { I18nManager } from 'react-native'; |
2 | 2 | import Animated from 'react-native-reanimated'; |
3 | 3 | import { CardInterpolationProps, CardInterpolatedStyle } from '../types'; |
| 4 | +import { getStatusBarHeight } from 'react-native-safe-area-view'; |
4 | 5 |
|
5 | | -const { cond, multiply, interpolate } = Animated; |
| 6 | +const { cond, add, multiply, interpolate } = Animated; |
6 | 7 |
|
7 | 8 | /** |
8 | 9 | * Standard iOS-style slide in from the right. |
@@ -71,6 +72,58 @@ export function forVerticalIOS({ |
71 | 72 | }; |
72 | 73 | } |
73 | 74 |
|
| 75 | +/** |
| 76 | + * Standard iOS-style modal animation in iOS 13. |
| 77 | + */ |
| 78 | +export function forModalPresentationIOS({ |
| 79 | + index, |
| 80 | + progress: { current, next }, |
| 81 | + layouts: { screen }, |
| 82 | +}: CardInterpolationProps): CardInterpolatedStyle { |
| 83 | + const topOffset = 10; |
| 84 | + const statusBarHeight = getStatusBarHeight(screen.width > screen.height); |
| 85 | + const aspectRatio = screen.height / screen.width; |
| 86 | + |
| 87 | + const progress = add(current, next ? next : 0); |
| 88 | + |
| 89 | + const translateY = interpolate(progress, { |
| 90 | + inputRange: [0, 1, 2], |
| 91 | + outputRange: [ |
| 92 | + screen.height, |
| 93 | + index === 0 ? 0 : topOffset, |
| 94 | + (index === 0 ? statusBarHeight : 0) - topOffset * aspectRatio, |
| 95 | + ], |
| 96 | + }); |
| 97 | + |
| 98 | + const overlayOpacity = interpolate(progress, { |
| 99 | + inputRange: [0, 1, 2], |
| 100 | + outputRange: [0, 0.3, 1], |
| 101 | + }); |
| 102 | + |
| 103 | + const scale = interpolate(progress, { |
| 104 | + inputRange: [0, 1, 2], |
| 105 | + outputRange: [1, 1, screen.width ? 1 - (topOffset * 2) / screen.width : 1], |
| 106 | + }); |
| 107 | + |
| 108 | + const borderRadius = |
| 109 | + index === 0 |
| 110 | + ? interpolate(progress, { |
| 111 | + inputRange: [0, 1, 2], |
| 112 | + outputRange: [0, 0, 10], |
| 113 | + }) |
| 114 | + : 10; |
| 115 | + |
| 116 | + return { |
| 117 | + cardStyle: { |
| 118 | + borderTopLeftRadius: borderRadius, |
| 119 | + borderTopRightRadius: borderRadius, |
| 120 | + marginTop: index === 0 ? 0 : statusBarHeight, |
| 121 | + transform: [{ translateY }, { scale }], |
| 122 | + }, |
| 123 | + overlayStyle: { opacity: overlayOpacity }, |
| 124 | + }; |
| 125 | +} |
| 126 | + |
74 | 127 | /** |
75 | 128 | * Standard Android-style fade in from the bottom for Android Oreo. |
76 | 129 | */ |
|
0 commit comments