From dc27f2fa3a5a127813586a040da0bb15d962474b Mon Sep 17 00:00:00 2001 From: Mo Gorhom Date: Fri, 29 Jan 2021 22:20:40 +0100 Subject: [PATCH 1/2] chore: replace touchable component with tap gesture handler --- .../BottomSheetBackdrop.tsx | 58 +++++++++---------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx b/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx index 1abb47a6c..620392a43 100644 --- a/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx +++ b/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx @@ -1,5 +1,4 @@ -import React, { memo, useCallback, useMemo, useRef } from 'react'; -import { TouchableWithoutFeedback } from 'react-native'; +import React, { memo, useMemo, useRef } from 'react'; import Animated, { interpolate, Extrapolate, @@ -7,7 +6,13 @@ import Animated, { useAnimatedProps, useSharedValue, useAnimatedReaction, + useAnimatedGestureHandler, + runOnJS, } from 'react-native-reanimated'; +import { + TapGestureHandler, + TapGestureHandlerGestureEvent, +} from 'react-native-gesture-handler'; import isEqual from 'lodash.isequal'; import { useBottomSheet } from '../../hooks/useBottomSheet'; import { @@ -21,10 +26,6 @@ import { WINDOW_HEIGHT } from '../../constants'; import type { BottomSheetDefaultBackdropProps } from './types'; import { styles } from './styles'; -const AnimatedTouchableWithoutFeedback = Animated.createAnimatedComponent( - TouchableWithoutFeedback -); - const BottomSheetBackdropComponent = ({ animatedIndex, opacity = DEFAULT_OPACITY, @@ -45,30 +46,27 @@ const BottomSheetBackdropComponent = ({ ]); //#endregion - //#region callbacks - const handleOnPress = useCallback(() => { - close(); - }, [close]); + //#region tap gesture + const gestureHandler = useAnimatedGestureHandler( + { + onStart: () => { + runOnJS(close)(); + }, + } + ); //#endregion //#region animated props const isContainerTouchable = useSharedValue(closeOnPress, true); - const containerAnimatedProps = useAnimatedProps(() => ({ - pointerEvents: isContainerTouchable.value ? 'auto' : 'none', - })); - //#endregion - - //#region styles - const buttonAnimatedStyle = useAnimatedStyle( + const containerAnimatedProps = useAnimatedProps( () => ({ - top: animatedIndex.value <= disappearsOnIndex ? WINDOW_HEIGHT : 0, + pointerEvents: animatedIndex.value > disappearsOnIndex ? 'auto' : 'none', }), [disappearsOnIndex] ); - const buttonStyle = useMemo(() => [style, buttonAnimatedStyle], [ - style, - buttonAnimatedStyle, - ]); + //#endregion + + //#region styles const containerAnimatedStyle = useAnimatedStyle( () => ({ opacity: interpolate( @@ -77,6 +75,7 @@ const BottomSheetBackdropComponent = ({ [0, 0, opacity], Extrapolate.CLAMP ), + top: animatedIndex.value <= disappearsOnIndex ? WINDOW_HEIGHT : 0, }), [opacity, disappearsOnIndex, appearsOnIndex] ); @@ -101,21 +100,18 @@ const BottomSheetBackdropComponent = ({ //#endregion return closeOnPress ? ( - + - + ) : ( ); From fb42739507cd97c9037e68e2626cfa9badca663c Mon Sep 17 00:00:00 2001 From: Mo Gorhom Date: Wed, 3 Feb 2021 20:02:17 +0100 Subject: [PATCH 2/2] chore: move snap points from js thread to native thread --- src/components/bottomSheet/BottomSheet.tsx | 5 ++-- src/hooks/useInteractivePanGestureHandler.ts | 31 ++++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/components/bottomSheet/BottomSheet.tsx b/src/components/bottomSheet/BottomSheet.tsx index 74349ede2..83b95ea48 100644 --- a/src/components/bottomSheet/BottomSheet.tsx +++ b/src/components/bottomSheet/BottomSheet.tsx @@ -253,6 +253,7 @@ const BottomSheetComponent = forwardRef( //#region gesture interaction / animation // variables const animationState = useSharedValue(ANIMATION_STATE.UNDETERMINED, false); + const animatedSnapPoints = useSharedValue(snapPoints, true); const animatedPosition = useSharedValue(initialPosition, true); const animatedIndex = useDerivedValue(() => { const adjustedSnapPoints = snapPoints.slice().reverse(); @@ -323,7 +324,7 @@ const BottomSheetComponent = forwardRef( ] = useInteractivePanGestureHandler( GESTURE.CONTENT, animatedPosition, - snapPoints, + animatedSnapPoints, animateToPoint, enableOverDrag, overDragResistanceFactor, @@ -336,7 +337,7 @@ const BottomSheetComponent = forwardRef( ] = useInteractivePanGestureHandler( GESTURE.HANDLE, animatedPosition, - snapPoints, + animatedSnapPoints, animateToPoint, enableOverDrag, overDragResistanceFactor diff --git a/src/hooks/useInteractivePanGestureHandler.ts b/src/hooks/useInteractivePanGestureHandler.ts index 757b75ba9..08486fd05 100644 --- a/src/hooks/useInteractivePanGestureHandler.ts +++ b/src/hooks/useInteractivePanGestureHandler.ts @@ -17,7 +17,7 @@ type InteractivePanGestureHandlerContextType = { export const useInteractivePanGestureHandler = ( type: GESTURE, animatedPosition: Animated.SharedValue, - snapPoints: number[], + snapPoints: Animated.SharedValue, animateToPoint: (point: number, velocity: number) => void, enableOverDrag: boolean, overDragResistanceFactor: number, @@ -56,33 +56,36 @@ export const useInteractivePanGestureHandler = ( const position = context.currentPosition + translationY; const negativeScrollableContentOffset = - context.currentPosition === snapPoints[snapPoints.length - 1] && + context.currentPosition === + snapPoints.value[snapPoints.value.length - 1] && scrollableContentOffsetY ? scrollableContentOffsetY.value * -1 : 0; const clampedPosition = clamp( position + negativeScrollableContentOffset, - snapPoints[snapPoints.length - 1], - snapPoints[0] + snapPoints.value[snapPoints.value.length - 1], + snapPoints.value[0] ); if (enableOverDrag) { if ( type === GESTURE.HANDLE && - position <= snapPoints[snapPoints.length - 1] + position <= snapPoints.value[snapPoints.value.length - 1] ) { const resistedPosition = - snapPoints[snapPoints.length - 1] - - Math.sqrt(1 + (snapPoints[snapPoints.length - 1] - position)) * + snapPoints.value[snapPoints.value.length - 1] - + Math.sqrt( + 1 + (snapPoints.value[snapPoints.value.length - 1] - position) + ) * overDragResistanceFactor; animatedPosition.value = resistedPosition; return; } - if (position >= snapPoints[0]) { + if (position >= snapPoints.value[0]) { const resistedPosition = - snapPoints[0] + - Math.sqrt(1 + (position - snapPoints[0])) * + snapPoints.value[0] + + Math.sqrt(1 + (position - snapPoints.value[0])) * overDragResistanceFactor; animatedPosition.value = resistedPosition; return; @@ -97,7 +100,7 @@ export const useInteractivePanGestureHandler = ( const destinationPoint = snapPoint( gestureTranslationY.value + context.currentPosition, gestureVelocityY.value, - snapPoints + snapPoints.value ); /** @@ -110,8 +113,10 @@ export const useInteractivePanGestureHandler = ( if ( (scrollableContentOffsetY ? scrollableContentOffsetY.value : 0) > 0 && - context.currentPosition === snapPoints[snapPoints.length - 1] && - animatedPosition.value === snapPoints[snapPoints.length - 1] + context.currentPosition === + snapPoints.value[snapPoints.value.length - 1] && + animatedPosition.value === + snapPoints.value[snapPoints.value.length - 1] ) { return; }