Skip to content

Commit 56c3c78

Browse files
committed
using scrollEnabled
1 parent aef0f5e commit 56c3c78

7 files changed

Lines changed: 53 additions & 207 deletions

File tree

src/components/bottomSheet/BottomSheet.tsx

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ import {
4949
KEYBOARD_STATE,
5050
KEYBOARD_BEHAVIOR,
5151
SHEET_STATE,
52-
SCROLLABLE_STATE,
5352
KEYBOARD_BLUR_BEHAVIOR,
5453
KEYBOARD_INPUT_MODE,
5554
ANIMATION_SOURCE,
@@ -288,6 +287,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
288287
const animatedHandleGestureState = useSharedValue<State>(
289288
State.UNDETERMINED
290289
);
290+
const isPanGestureMoving = useSharedValue(false);
291291
//#endregion
292292

293293
//#region hooks variables
@@ -366,35 +366,6 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
366366
isInTemporaryPosition,
367367
keyboardBehavior,
368368
]);
369-
const animatedScrollableState = useDerivedValue<SCROLLABLE_STATE>(() => {
370-
/**
371-
* if sheet state is fill parent, then unlock scrolling
372-
*/
373-
if (animatedSheetState.value === SHEET_STATE.FILL_PARENT) {
374-
return SCROLLABLE_STATE.UNLOCKED;
375-
}
376-
377-
/**
378-
* if sheet state is extended, then unlock scrolling
379-
*/
380-
if (animatedSheetState.value === SHEET_STATE.EXTENDED) {
381-
return SCROLLABLE_STATE.UNLOCKED;
382-
}
383-
384-
/**
385-
* if keyboard is shown and sheet is animating
386-
* then we do not lock the scrolling to not lose
387-
* current scrollable scroll position.
388-
*/
389-
if (
390-
animatedKeyboardState.value === KEYBOARD_STATE.SHOWN &&
391-
animatedAnimationState.value === ANIMATION_STATE.RUNNING
392-
) {
393-
return SCROLLABLE_STATE.UNLOCKED;
394-
}
395-
396-
return SCROLLABLE_STATE.LOCKED;
397-
});
398369
// dynamic
399370
const animatedContentHeightMax = useDerivedValue(() => {
400371
const keyboardHeightInContainer = animatedKeyboardHeightInContainer.value;
@@ -509,6 +480,14 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
509480

510481
return currentIndex;
511482
}, [android_keyboardInputMode]);
483+
const isExpanded = useDerivedValue(() => {
484+
const state = animatedSheetState.value;
485+
return (
486+
state === SHEET_STATE.EXTENDED ||
487+
state === SHEET_STATE.OVER_EXTENDED ||
488+
state === SHEET_STATE.FILL_PARENT
489+
);
490+
}, [animatedSheetState]);
512491
//#endregion
513492

514493
//#region private methods
@@ -1111,9 +1090,9 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
11111090
enablePanDownToClose,
11121091
animatedAnimationState,
11131092
animatedSheetState,
1114-
animatedScrollableState,
11151093
animatedContentGestureState,
11161094
animatedHandleGestureState,
1095+
isPanGestureMoving,
11171096
animatedKeyboardState,
11181097
animatedScrollableType,
11191098
animatedIndex,
@@ -1131,6 +1110,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
11311110
isInTemporaryPosition,
11321111
isContentHeightFixed,
11331112
isScrollableRefreshable,
1113+
isExpanded,
11341114
shouldHandleKeyboardEvents,
11351115
simultaneousHandlers: _providedSimultaneousHandlers,
11361116
waitFor: _providedWaitFor,
@@ -1159,11 +1139,11 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
11591139
animatedKeyboardHeightInContainer,
11601140
animatedSheetState,
11611141
animatedHighestSnapPoint,
1162-
animatedScrollableState,
11631142
animatedSnapPoints,
11641143
shouldHandleKeyboardEvents,
11651144
animatedScrollableContentOffsetY,
11661145
isScrollableRefreshable,
1146+
isExpanded,
11671147
isContentHeightFixed,
11681148
isInTemporaryPosition,
11691149
enableContentPanningGesture,

src/components/bottomSheetRefreshControl/BottomSheetRefreshControl.android.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { RefreshControl, RefreshControlProps } from 'react-native';
33
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
44
import Animated, { useAnimatedProps } from 'react-native-reanimated';
55
import { BottomSheetDraggableContext } from '../../contexts/gesture';
6-
import { SCROLLABLE_STATE } from '../../constants';
76
import { useBottomSheetInternal } from '../../hooks';
87

98
const AnimatedRefreshControl = Animated.createAnimatedComponent(RefreshControl);
@@ -16,12 +15,12 @@ function BottomSheetRefreshControlComponent({
1615
}: BottomSheetRefreshControlProps) {
1716
//#region hooks
1817
const draggableGesture = useContext(BottomSheetDraggableContext);
19-
const { animatedScrollableState } = useBottomSheetInternal();
18+
const { isExpanded } = useBottomSheetInternal();
2019
//#endregion
2120

2221
//#region variables
2322
const animatedProps = useAnimatedProps(() => ({
24-
enabled: animatedScrollableState.value === SCROLLABLE_STATE.UNLOCKED,
23+
enabled: isExpanded.value,
2524
}));
2625
const gesture = useMemo(
2726
() =>

src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
useBottomSheetInternal,
77
useStableCallback,
88
} from '../../hooks';
9-
import { SCROLLABLE_STATE, SCROLLABLE_TYPE } from '../../constants';
9+
import type { SCROLLABLE_TYPE } from '../../constants';
1010

1111
export function createBottomSheetScrollableComponent<T, P>(
1212
type: SCROLLABLE_TYPE,
@@ -44,20 +44,33 @@ export function createBottomSheetScrollableComponent<T, P>(
4444
const {
4545
animatedScrollableRef: scrollableRef,
4646
animatedFooterHeight,
47-
animatedScrollableState,
47+
isExpanded,
4848
enableDynamicSizing,
4949
animatedContentHeight,
50+
animatedScrollableContentOffsetY,
51+
isPanGestureMoving,
5052
} = useBottomSheetInternal();
5153
//#endregion
5254

5355
//#region variables
5456
const scrollableAnimatedProps = useAnimatedProps(
5557
() => ({
58+
// only scroll if sheet is open
59+
scrollEnabled: isExpanded.value,
60+
// only bounce at bottom or not touching screen
61+
bounces:
62+
animatedScrollableContentOffsetY.value > 0 ||
63+
!isPanGestureMoving.value,
5664
showsVerticalScrollIndicator: showsVerticalScrollIndicator
57-
? animatedScrollableState.value === SCROLLABLE_STATE.UNLOCKED
65+
? isExpanded.value
5866
: showsVerticalScrollIndicator,
5967
}),
60-
[showsVerticalScrollIndicator]
68+
[
69+
animatedScrollableContentOffsetY,
70+
isPanGestureMoving,
71+
isExpanded,
72+
showsVerticalScrollIndicator,
73+
]
6174
);
6275
//#endregion
6376

src/constants.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,6 @@ enum SHEET_STATE {
1919
FILL_PARENT,
2020
}
2121

22-
enum SCROLLABLE_STATE {
23-
LOCKED = 0,
24-
UNLOCKED,
25-
UNDETERMINED,
26-
}
27-
2822
enum SCROLLABLE_TYPE {
2923
UNDETERMINED = 0,
3024
VIEW,
@@ -113,7 +107,6 @@ export {
113107
ANIMATION_METHOD,
114108
ANIMATION_SOURCE,
115109
SCROLLABLE_TYPE,
116-
SCROLLABLE_STATE,
117110
KEYBOARD_STATE,
118111
WINDOW_HEIGHT,
119112
WINDOW_WIDTH,

src/contexts/internal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import type {
1010
import type {
1111
ANIMATION_STATE,
1212
KEYBOARD_STATE,
13-
SCROLLABLE_STATE,
1413
SCROLLABLE_TYPE,
1514
SHEET_STATE,
1615
} from '../constants';
@@ -31,10 +30,10 @@ export interface BottomSheetInternalContextType
3130
// animated states
3231
animatedAnimationState: Animated.SharedValue<ANIMATION_STATE>;
3332
animatedSheetState: Animated.SharedValue<SHEET_STATE>;
34-
animatedScrollableState: Animated.SharedValue<SCROLLABLE_STATE>;
3533
animatedKeyboardState: Animated.SharedValue<KEYBOARD_STATE>;
3634
animatedContentGestureState: Animated.SharedValue<State>;
3735
animatedHandleGestureState: Animated.SharedValue<State>;
36+
isPanGestureMoving: Animated.SharedValue<boolean>;
3837

3938
// animated values
4039
animatedSnapPoints: Animated.SharedValue<number[]>;
@@ -51,6 +50,7 @@ export interface BottomSheetInternalContextType
5150
animatedScrollableType: Animated.SharedValue<SCROLLABLE_TYPE>;
5251
animatedScrollableContentOffsetY: Animated.SharedValue<number>;
5352
isScrollableRefreshable: Animated.SharedValue<boolean>;
53+
isExpanded: Animated.SharedValue<boolean>;
5454
isContentHeightFixed: Animated.SharedValue<boolean>;
5555
isInTemporaryPosition: Animated.SharedValue<boolean>;
5656
shouldHandleKeyboardEvents: Animated.SharedValue<boolean>;

src/hooks/useGestureEventsHandlers.tsx

Lines changed: 11 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@ import { floatingPointEquals } from '../utilities';
2323
type GestureEventContextType = {
2424
initialPosition: number;
2525
initialKeyboardState: KEYBOARD_STATE;
26-
isScrollablePositionLocked: boolean;
2726
};
2827

2928
const INITIAL_CONTEXT: GestureEventContextType = {
3029
initialPosition: 0,
3130
initialKeyboardState: KEYBOARD_STATE.UNDETERMINED,
32-
isScrollablePositionLocked: false,
3331
};
3432

3533
const dismissKeyboard = Keyboard.dismiss;
@@ -59,6 +57,7 @@ export const useGestureEventsHandlers: GestureEventsHandlersHookType = () => {
5957
overDragResistanceFactor,
6058
isInTemporaryPosition,
6159
isScrollableRefreshable,
60+
isPanGestureMoving,
6261
animateToPosition,
6362
stopAnimation,
6463
} = useBottomSheetInternal();
@@ -70,8 +69,11 @@ export const useGestureEventsHandlers: GestureEventsHandlersHookType = () => {
7069

7170
//#region gesture methods
7271
const handleOnBegin: GestureEventHandlerCallbackType = useWorkletCallback(
73-
function handleOnBegin(__, _) {},
74-
[]
72+
function handleOnBegin(__, _) {
73+
// touching screen
74+
isPanGestureMoving.value = true;
75+
},
76+
[isPanGestureMoving]
7577
);
7678
const handleOnStart: GestureEventHandlerCallbackType = useWorkletCallback(
7779
function handleOnStart(__, _) {
@@ -84,17 +86,6 @@ export const useGestureEventsHandlers: GestureEventsHandlersHookType = () => {
8486
initialPosition: animatedPosition.value,
8587
initialKeyboardState: animatedKeyboardState.value,
8688
};
87-
88-
/**
89-
* if the scrollable content is scrolled, then
90-
* we lock the position.
91-
*/
92-
if (animatedScrollableContentOffsetY.value > 0) {
93-
context.value = {
94-
...context.value,
95-
isScrollablePositionLocked: true,
96-
};
97-
}
9889
},
9990
[
10091
stopAnimation,
@@ -145,57 +136,21 @@ export const useGestureEventsHandlers: GestureEventsHandlersHookType = () => {
145136
return;
146137
}
147138

148-
/**
149-
* a negative scrollable content offset to be subtracted from accumulated
150-
* current position and gesture translation Y to allow user to drag the sheet,
151-
* when scrollable position at the top.
152-
* a negative scrollable content offset when the scrollable is not locked.
153-
*/
154-
const negativeScrollableContentOffset =
155-
(floatingPointEquals(context.value.initialPosition, highestSnapPoint) &&
156-
source === GESTURE_SOURCE.CONTENT) ||
157-
!context.value.isScrollablePositionLocked
158-
? animatedScrollableContentOffsetY.value * -1
159-
: 0;
160-
161139
/**
162140
* an accumulated value of starting position with gesture translation y.
163141
*/
164142
const draggedPosition = context.value.initialPosition + translationY;
165143

166-
/**
167-
* an accumulated value of dragged position and negative scrollable content offset,
168-
* this will insure locking sheet position when user is scrolling the scrollable until,
169-
* they reach to the top of the scrollable.
170-
*/
171-
const accumulatedDraggedPosition =
172-
draggedPosition + negativeScrollableContentOffset;
173-
174144
/**
175145
* a clamped value of the accumulated dragged position, to insure keeping the dragged
176146
* position between the highest and lowest snap points.
177147
*/
178148
const clampedPosition = clamp(
179-
accumulatedDraggedPosition,
149+
draggedPosition,
180150
highestSnapPoint,
181151
lowestSnapPoint
182152
);
183153

184-
/**
185-
* if scrollable position is locked and the animated position
186-
* reaches the highest point, then we unlock the scrollable position.
187-
*/
188-
if (
189-
context.value.isScrollablePositionLocked &&
190-
source === GESTURE_SOURCE.CONTENT &&
191-
floatingPointEquals(animatedPosition.value, highestSnapPoint)
192-
) {
193-
context.value = {
194-
...context.value,
195-
isScrollablePositionLocked: false,
196-
};
197-
}
198-
199154
/**
200155
* over-drag implementation.
201156
*/
@@ -227,16 +182,11 @@ export const useGestureEventsHandlers: GestureEventsHandlersHookType = () => {
227182

228183
if (
229184
source === GESTURE_SOURCE.CONTENT &&
230-
draggedPosition + negativeScrollableContentOffset > lowestSnapPoint
185+
draggedPosition > lowestSnapPoint
231186
) {
232187
const resistedPosition =
233188
lowestSnapPoint +
234-
Math.sqrt(
235-
1 +
236-
(draggedPosition +
237-
negativeScrollableContentOffset -
238-
lowestSnapPoint)
239-
) *
189+
Math.sqrt(1 + (draggedPosition - lowestSnapPoint)) *
240190
overDragResistanceFactor;
241191
animatedPosition.value = resistedPosition;
242192
return;
@@ -402,8 +352,9 @@ export const useGestureEventsHandlers: GestureEventsHandlersHookType = () => {
402352
const handleOnFinalize: GestureEventHandlerCallbackType = useWorkletCallback(
403353
function handleOnFinalize() {
404354
resetContext(context);
355+
isPanGestureMoving.value = false;
405356
},
406-
[context]
357+
[context, isPanGestureMoving]
407358
);
408359
//#endregion
409360

0 commit comments

Comments
 (0)