Skip to content

Commit bd2f7a8

Browse files
committed
fix(tablet): fix issue with tablet and rotation
1 parent 4285765 commit bd2f7a8

File tree

6 files changed

+90
-10
lines changed

6 files changed

+90
-10
lines changed

example/app.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"name": "example",
44
"slug": "example",
55
"version": "1.0.0",
6-
"orientation": "portrait",
76
"icon": "./assets/icon.png",
87
"userInterfaceStyle": "light",
98
"newArchEnabled": true,

example/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"dependencies": {
1212
"@gorhom/bottom-sheet": "^4.6.3",
1313
"expo": "~52.0.38",
14+
"expo-screen-orientation": "~8.0.4",
1415
"expo-status-bar": "~2.0.1",
1516
"react": "18.3.1",
1617
"react-dom": "18.3.1",

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"eslint": "^8.51.0",
6666
"eslint-config-prettier": "^9.0.0",
6767
"eslint-plugin-prettier": "^5.0.1",
68+
"expo-screen-orientation": "^8.0.4",
6869
"jest": "^29.7.0",
6970
"prettier": "^3.0.3",
7071
"react": "18.3.1",
@@ -79,6 +80,7 @@
7980
"@types/react": "^18.2.44"
8081
},
8182
"peerDependencies": {
83+
"expo-screen-orientation": "*",
8284
"react": "*",
8385
"react-native": "*",
8486
"react-native-reanimated": ">=2.0.0",

src/Provider.tsx

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { Platform } from 'react-native';
3232

3333
import { useKeyboard } from './useKeyboard';
3434
import { useSafeAreaInsets } from 'react-native-safe-area-context';
35+
import { useOrientation } from './useOrientation';
3536

3637
export type RefType = TextInput | View | Animated.View | null;
3738

@@ -58,7 +59,7 @@ function Wrapper(props: PropsWithChildren<{}>) {
5859
style={styles.wrapper}
5960
ref={wrapperRef}
6061
onLayout={({ nativeEvent }) => {
61-
if (nativeEvent.layout.height < windowDimensions.height) {
62+
if (nativeEvent.layout.height !== windowDimensions.height) {
6263
setWrapperOffset(windowDimensions.height - nativeEvent.layout.height);
6364
}
6465
}}
@@ -94,6 +95,7 @@ const SmartScrollContext = React.createContext<{
9495
inputs: InputType;
9596
setInputs: React.Dispatch<React.SetStateAction<InputType>>;
9697
currentFocus?: null | Elements[0];
98+
clearFocus: () => void;
9799
} | null>(null);
98100

99101
const SmartScrollProvider = ({ children }: { children: React.ReactNode }) => {
@@ -113,6 +115,18 @@ const SmartScrollProvider = ({ children }: { children: React.ReactNode }) => {
113115
[elements]
114116
);
115117

118+
const clearFocus = useCallback(() => {
119+
if (!currentFocus) return;
120+
121+
setElements((els) => ({
122+
...els,
123+
[currentFocus.name]: {
124+
...currentFocus,
125+
isFocus: false,
126+
},
127+
}));
128+
}, [elements, currentFocus]);
129+
116130
// we have a flick on first focus so we make the scrollview wait a bit before animate
117131
useLayoutEffect(() => {
118132
if (currentFocus && !isReady) {
@@ -136,6 +150,7 @@ const SmartScrollProvider = ({ children }: { children: React.ReactNode }) => {
136150
currentFocus,
137151
inputs,
138152
setInputs,
153+
clearFocus,
139154
}}
140155
>
141156
{children}
@@ -204,6 +219,7 @@ export function useFormSmartScroll({
204219
wrapperOffset,
205220
inputs,
206221
setInputs,
222+
clearFocus,
207223
} = useSmartScrollContext();
208224

209225
const _keyboard = useKeyboard();
@@ -214,6 +230,17 @@ export function useFormSmartScroll({
214230

215231
const translateY = useSharedValue(0);
216232

233+
const orientation = useOrientation();
234+
235+
const keyboardEnd = _keyboard.coordinates.end.screenY;
236+
237+
useEffect(() => {
238+
translateY.value = 0;
239+
scrollY.value = 0;
240+
clearFocus();
241+
Keyboard.dismiss();
242+
}, [orientation]);
243+
217244
useEffect(() => {
218245
const sub = Keyboard.addListener('keyboardWillHide', () => {
219246
translateY.value = withTiming(0);
@@ -230,14 +257,11 @@ export function useFormSmartScroll({
230257
if (!focus) return;
231258

232259
if (isAndroid) {
233-
if (
234-
focus.position + wrapperOffset >
235-
_keyboard.coordinates.end.screenY - focus.height * 2
236-
) {
260+
if (focus.position + wrapperOffset > keyboardEnd - focus.height * 2) {
237261
if (wrapperOffset) {
238262
const diff =
239263
Math.abs(
240-
_keyboard.coordinates.end.screenY -
264+
keyboardEnd -
241265
focus.position -
242266
focus.height -
243267
padding +
@@ -259,15 +283,16 @@ export function useFormSmartScroll({
259283

260284
if (
261285
focus.position + wrapperOffset >
262-
_keyboard.coordinates.end.screenY - focus.height + scrollY.value
286+
keyboardEnd - focus.height + scrollY.value
263287
) {
264288
const diff = Math.abs(
265-
_keyboard.coordinates.end.screenY -
289+
keyboardEnd -
266290
focus.position -
267291
focus.height -
268292
padding +
269293
scrollY.value -
270-
wrapperOffset
294+
wrapperOffset -
295+
insets.bottom
271296
);
272297
translateY.value = withTiming(-diff);
273298

src/useOrientation.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { useEffect, useState } from 'react';
2+
import * as ScreenOrientation from 'expo-screen-orientation';
3+
4+
export function useOrientation(): ScreenOrientation.Orientation {
5+
const [orientation, setOrientation] = useState<ScreenOrientation.Orientation>(
6+
ScreenOrientation.Orientation.PORTRAIT_UP
7+
);
8+
9+
const getInitialOrientation = async () => {
10+
const initial = await ScreenOrientation.getOrientationAsync();
11+
12+
setOrientation(initial);
13+
};
14+
15+
useEffect(() => {
16+
getInitialOrientation();
17+
}, []);
18+
19+
useEffect(() => {
20+
const listener = ScreenOrientation.addOrientationChangeListener((event) => {
21+
setOrientation(event.orientationInfo.orientation);
22+
});
23+
24+
return () => {
25+
ScreenOrientation.removeOrientationChangeListener(listener);
26+
};
27+
}, []);
28+
29+
return orientation;
30+
}

yarn.lock

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ __metadata:
4949
babel-loader: ^8.1.0
5050
babel-plugin-module-resolver: ^5.0.0
5151
expo: ~52.0.38
52+
expo-screen-orientation: ~8.0.4
5253
expo-status-bar: ~2.0.1
5354
react: 18.3.1
5455
react-dom: 18.3.1
@@ -75,6 +76,7 @@ __metadata:
7576
eslint: ^8.51.0
7677
eslint-config-prettier: ^9.0.0
7778
eslint-plugin-prettier: ^5.0.1
79+
expo-screen-orientation: ^8.0.4
7880
jest: ^29.7.0
7981
prettier: ^3.0.3
8082
react: 18.3.1
@@ -85,6 +87,7 @@ __metadata:
8587
release-it: ^17.0.0
8688
typescript: ^5.2.2
8789
peerDependencies:
90+
expo-screen-orientation: "*"
8891
react: "*"
8992
react-native: "*"
9093
react-native-reanimated: ">=2.0.0"
@@ -8616,6 +8619,26 @@ __metadata:
86168619
languageName: node
86178620
linkType: hard
86188621

8622+
"expo-screen-orientation@npm:^8.0.4":
8623+
version: 8.1.1
8624+
resolution: "expo-screen-orientation@npm:8.1.1"
8625+
peerDependencies:
8626+
expo: "*"
8627+
react-native: "*"
8628+
checksum: 7808336110a49e80e57ff24a03b59a381ad19a93b083edc075ef5d0791db628a8d51638bcb1d86d4e0d80ee7d298633b3619c515e96b56ca9bdf3c59947a310b
8629+
languageName: node
8630+
linkType: hard
8631+
8632+
"expo-screen-orientation@npm:~8.0.4":
8633+
version: 8.0.4
8634+
resolution: "expo-screen-orientation@npm:8.0.4"
8635+
peerDependencies:
8636+
expo: "*"
8637+
react-native: "*"
8638+
checksum: 090d56a754427c2402cfdcaabd1653e3d54d70aee67a8e7b46f4953556d9f091785dd97a749e92a841747de9be8d9adb49146d3898b2eaf1c3c4e1b11d8ac4e3
8639+
languageName: node
8640+
linkType: hard
8641+
86198642
"expo-status-bar@npm:~2.0.1":
86208643
version: 2.0.1
86218644
resolution: "expo-status-bar@npm:2.0.1"

0 commit comments

Comments
 (0)