From 6ae75c8ef03719e8e0de23fa78c8020f84c07ea9 Mon Sep 17 00:00:00 2001 From: Hailey Date: Fri, 4 Oct 2024 10:38:17 -0700 Subject: [PATCH] disable drag android when needed --- .../modules/bottomsheet/BottomSheetModule.kt | 4 ++ .../modules/bottomsheet/BottomSheetView.kt | 15 ++++++++ modules/bottom-sheet/src/BottomSheet.types.ts | 1 + src/components/Dialog/context.ts | 2 + src/components/Dialog/index.tsx | 37 +++++++++++++++---- src/components/Dialog/types.ts | 2 + 6 files changed, 53 insertions(+), 8 deletions(-) diff --git a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetModule.kt b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetModule.kt index fe3b34aa8b..057e6ed2e2 100644 --- a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetModule.kt +++ b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetModule.kt @@ -29,6 +29,10 @@ class BottomSheetModule : Module() { view.updateLayout() } + Prop("disableDrag") { view: BottomSheetView, prop: Boolean -> + view.disableDrag = prop + } + Prop("minHeight") { view: BottomSheetView, prop: Float -> view.minHeight = prop } diff --git a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt index 6cfd24e50a..a5a84ec3d9 100644 --- a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt +++ b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt @@ -39,6 +39,12 @@ class BottomSheetView( private val onStateChange by EventDispatcher() // Props + var disableDrag = false + set (value) { + field = value + this.setDraggable(!value) + } + var preventDismiss = false set(value) { field = value @@ -273,6 +279,15 @@ class BottomSheetView( return ratio } + private fun setDraggable(draggable: Boolean) { + val dialog = this.dialog ?: return + val bottomSheet = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet) + bottomSheet?.let { + val behavior = BottomSheetBehavior.from(it) + behavior.isDraggable = draggable + } + } + override fun onHostResume() { } override fun onHostPause() { } diff --git a/modules/bottom-sheet/src/BottomSheet.types.ts b/modules/bottom-sheet/src/BottomSheet.types.ts index 98c1c4f6e8..150932d423 100644 --- a/modules/bottom-sheet/src/BottomSheet.types.ts +++ b/modules/bottom-sheet/src/BottomSheet.types.ts @@ -24,6 +24,7 @@ export interface BottomSheetViewProps { preventExpansion?: boolean backgroundColor?: ColorValue containerBackgroundColor?: ColorValue + disableDrag?: boolean minHeight?: number maxHeight?: number diff --git a/src/components/Dialog/context.ts b/src/components/Dialog/context.ts index 6247b6d3d1..b479bc7f06 100644 --- a/src/components/Dialog/context.ts +++ b/src/components/Dialog/context.ts @@ -12,6 +12,8 @@ export const Context = React.createContext({ close: () => {}, isNativeDialog: false, nativeSnapPoint: BottomSheetSnapPoint.Hidden, + disableDrag: false, + setDisableDrag: () => {}, }) export function useDialogContext() { diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index b2aba54232..49b5e10b23 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -1,5 +1,7 @@ import React, {useImperativeHandle} from 'react' import { + NativeScrollEvent, + NativeSyntheticEvent, Pressable, ScrollView, StyleProp, @@ -17,7 +19,7 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {logger} from '#/logger' -import {isIOS} from '#/platform/detection' +import {isAndroid, isIOS} from '#/platform/detection' import {useA11y} from '#/state/a11y' import {useDialogStateControlContext} from '#/state/dialogs' import {List, ListMethods, ListProps} from '#/view/com/util/List' @@ -60,6 +62,7 @@ export function Outer({ BottomSheetSnapPoint.Hidden, ) + const [disableDrag, setDisableDrag] = React.useState(false) const [snapPoint, setSnapPoint] = React.useState( BottomSheetSnapPoint.Partial, ) @@ -140,8 +143,14 @@ export function Outer({ ) const context = React.useMemo( - () => ({close, isNativeDialog: true, nativeSnapPoint: snapPoint}), - [close, snapPoint], + () => ({ + close, + isNativeDialog: true, + nativeSnapPoint: snapPoint, + disableDrag, + setDisableDrag, + }), + [close, snapPoint, disableDrag, setDisableDrag], ) return ( @@ -149,11 +158,12 @@ export function Outer({ + {...nativeOptions} + onSnapPointChange={onSnapPointChange} + onStateChange={onStateChange} + disableDrag={disableDrag}> {children} @@ -180,7 +190,7 @@ export function Inner({children, style}: DialogInnerProps) { export const ScrollableInner = React.forwardRef( function ScrollableInner({children, style, ...props}, ref) { - const {nativeSnapPoint} = useDialogContext() + const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext() const insets = useSafeAreaInsets() const [keyboardHeight, setKeyboardHeight] = React.useState(0) useKeyboardHandler({ @@ -198,6 +208,15 @@ export const ScrollableInner = React.forwardRef( const paddingBottom = nativeSnapPoint === BottomSheetSnapPoint.Full ? fullPadding : basePading + const onScroll = (e: NativeSyntheticEvent) => { + const {contentOffset} = e.nativeEvent + if (contentOffset.y > 0 && !disableDrag) { + setDisableDrag(true) + } else if (contentOffset.y <= 1 && disableDrag) { + setDisableDrag(false) + } + } + return ( ( ref={ref} {...props} bounces={nativeSnapPoint === BottomSheetSnapPoint.Full} - bottomOffset={30}> + bottomOffset={30} + scrollEventThrottle={50} + onScroll={isAndroid ? onScroll : undefined}> {children} ) diff --git a/src/components/Dialog/types.ts b/src/components/Dialog/types.ts index cf698bf5b0..caa787535b 100644 --- a/src/components/Dialog/types.ts +++ b/src/components/Dialog/types.ts @@ -41,6 +41,8 @@ export type DialogContextProps = { close: DialogControlProps['close'] isNativeDialog: boolean nativeSnapPoint: BottomSheetSnapPoint + disableDrag: boolean + setDisableDrag: React.Dispatch> } export type DialogControlOpenOptions = {