Skip to content

Commit

Permalink
fix: updated keyboard handling for Android
Browse files Browse the repository at this point in the history
  • Loading branch information
gorhom committed Jun 27, 2021
1 parent 2c2ca4e commit 2d74ab0
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 111 deletions.
2 changes: 1 addition & 1 deletion example/src/screens/advanced/KeyboardHandlingExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const KeyboardHandlingExample = () => {
const bottomSheetRef = useRef<BottomSheet>(null);

// variables
const snapPoints = useMemo(() => [SEARCH_HANDLE_HEIGHT + 34, 500], []);
const snapPoints = useMemo(() => [SEARCH_HANDLE_HEIGHT + 34, 450], []);

// callbacks
const handleToggleKeyboardBehavior = useCallback(() => {
Expand Down
166 changes: 77 additions & 89 deletions src/components/bottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import {
SHEET_STATE,
SCROLLABLE_STATE,
KEYBOARD_BLUR_BEHAVIOR,
KEYBOARD_INPUT_MODE,
KEYBOARD_DISMISS_THRESHOLD,
SCROLLABLE_TYPE,
WINDOW_HEIGHT,
Expand All @@ -73,7 +72,6 @@ import {
DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE,
INITIAL_CONTAINER_OFFSET,
DEFAULT_ANIMATION_CONFIGS,
DEFAULT_KEYBOARD_INPUT_MODE,
} from './constants';
import type { BottomSheetMethods, Insets } from '../../types';
import type { BottomSheetProps } from './types';
Expand Down Expand Up @@ -114,7 +112,6 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
// keyboard
keyboardBehavior = DEFAULT_KEYBOARD_BEHAVIOR,
keyboardBlurBehavior = DEFAULT_KEYBOARD_BLUR_BEHAVIOR,
android_keyboardInputMode = DEFAULT_KEYBOARD_INPUT_MODE,

// layout
handleHeight: _providedHandleHeight,
Expand Down Expand Up @@ -285,20 +282,19 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
/**
* Returns keyboard height that in the root container.
*/
const getKeyboardHeightInContainer = useWorkletCallback(() => {
'worklet';
/**
* if android software input mode is not `adjustPan`, than keyboard
* height will be 0 all the time.
*/
if (android_keyboardInputMode === KEYBOARD_INPUT_MODE.adjustResize) {
return 0;
}
return $modal
? animatedKeyboardHeight.value -
Math.abs(bottomInset - animatedContainerOffset.value.bottom)
: animatedKeyboardHeight.value - animatedContainerOffset.value.bottom;
}, [$modal, bottomInset]);
const getKeyboardHeightInContainer = useWorkletCallback(
() =>
$modal
? Math.abs(
animatedKeyboardHeight.value -
Math.abs(bottomInset - animatedContainerOffset.value.bottom)
)
: Math.abs(
animatedKeyboardHeight.value -
animatedContainerOffset.value.bottom
),
[$modal, bottomInset]
);
//#endregion

//#region state/dynamic variables
Expand Down Expand Up @@ -344,7 +340,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
}

return SHEET_STATE.OPENED;
});
}, [keyboardBehavior]);
const animatedScrollableState = useDerivedValue(() => {
/**
* if sheet state is fill parent, then unlock scrolling
Expand Down Expand Up @@ -376,76 +372,65 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
});
// dynamic
const animatedContentHeight = useDerivedValue(() => {
const contentHeight =
animatedSheetHeight.value - animatedHandleHeight.value;

/**
* before the container is measured, `contentHeight` value will be below zero,
* which will lead to freeze the scrollable on Android.
*
* @link (https://github.com/gorhom/react-native-bottom-sheet/issues/470)
*/
if (contentHeight <= 0) {
return 0;
}
const keyboardHeightInContainer = getKeyboardHeightInContainer();
let contentHeight =
animatedSheetHeight.value - animatedHandleHeight.value;

if (
(keyboardBehavior === KEYBOARD_BEHAVIOR.none ||
keyboardBehavior === KEYBOARD_BEHAVIOR.extend) &&
animatedKeyboardState.value === KEYBOARD_STATE.SHOWN
) {
return contentHeight - keyboardHeightInContainer;
}

if (
contentHeight = contentHeight - keyboardHeightInContainer;
} else if (
keyboardBehavior === KEYBOARD_BEHAVIOR.fillParent &&
isInTemporaryPosition.value
) {
if (animatedKeyboardState.value === KEYBOARD_STATE.SHOWN) {
return (
contentHeight =
animatedContainerHeight.value -
animatedHandleHeight.value -
keyboardHeightInContainer
);
keyboardHeightInContainer;
} else {
contentHeight =
animatedContainerHeight.value - animatedHandleHeight.value;
}
return animatedContainerHeight.value - animatedHandleHeight.value;
}

if (
} else if (
keyboardBehavior === KEYBOARD_BEHAVIOR.interactive &&
isInTemporaryPosition.value
) {
const contentWithKeyboardHeight =
contentHeight + keyboardHeightInContainer;

if (animatedKeyboardState.value === KEYBOARD_STATE.SHOWN) {
if (
keyboardHeightInContainer + animatedSheetHeight.value >
animatedContainerHeight.value
) {
return (
contentHeight =
animatedContainerHeight.value -
keyboardHeightInContainer -
animatedHandleHeight.value
);
animatedHandleHeight.value;
}

return contentHeight;
}

const contentWithKeyboardHeight =
contentHeight + keyboardHeightInContainer;

if (
} else if (
contentWithKeyboardHeight + animatedHandleHeight.value >
animatedContainerHeight.value
) {
return animatedContainerHeight.value - animatedHandleHeight.value;
contentHeight =
animatedContainerHeight.value - animatedHandleHeight.value;
} else {
contentHeight = contentWithKeyboardHeight;
}

return contentWithKeyboardHeight;
}

return contentHeight;
});
/**
* before the container is measured, `contentHeight` value will be below zero,
* which will lead to freeze the scrollable.
*
* @link (https://github.com/gorhom/react-native-bottom-sheet/issues/470)
*/
return Math.max(contentHeight, 0);
}, [keyboardBehavior]);
const animatedIndex = useDerivedValue(() => {
const adjustedSnapPoints = animatedSnapPoints.value.slice().reverse();
const adjustedSnapPointsIndexes = animatedSnapPoints.value
Expand Down Expand Up @@ -485,6 +470,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
const currentIndex = animatedCurrentIndex.value;
const snapPoints = animatedSnapPoints.value;
const keyboardState = animatedKeyboardState.value;
const highestSnapPoint = animatedHighestSnapPoint.value;

/**
* Handle restore sheet position on blur
Expand All @@ -507,8 +493,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
keyboardBehavior === KEYBOARD_BEHAVIOR.extend &&
keyboardState === KEYBOARD_STATE.SHOWN
) {
const nextPosition = snapPoints[snapPoints.length - 1];
return nextPosition;
return highestSnapPoint;
}

/**
Expand All @@ -530,9 +515,12 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
keyboardState === KEYBOARD_STATE.SHOWN
) {
isInTemporaryPosition.value = true;
const nextPosition = snapPoints[snapPoints.length - 1];
const keyboardHeightInContainer = getKeyboardHeightInContainer();
return Math.max(0, nextPosition - keyboardHeightInContainer);
return Math.max(0, highestSnapPoint - keyboardHeightInContainer);
}

if (isInTemporaryPosition.value) {
return animatedPosition.value;
}

return snapPoints[currentIndex];
Expand All @@ -550,32 +538,30 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
},
});

if (
Platform.OS === 'android' &&
isInTemporaryPosition.value === false &&
animatedKeyboardState.value === KEYBOARD_STATE.SHOWN
) {
Keyboard.dismiss();
}

if (_providedOnChange) {
_providedOnChange(index);
}
},
[
_providedOnChange,
animatedCurrentIndex,
animatedKeyboardState,
isInTemporaryPosition,
]
[_providedOnChange, animatedCurrentIndex]
);
const handleOnAnimate = useCallback(
(toPoint: number) => {
function handleOnAnimate(toPoint: number) {
const snapPoints = animatedSnapPoints.value;
const toIndex = snapPoints.indexOf(toPoint);

print({
component: BottomSheet.name,
method: handleOnAnimate.name,
params: {
toIndex,
fromIndex: animatedCurrentIndex.value,
},
});

if (!_providedOnAnimate) {
return;
}
const snapPoints = animatedSnapPoints.value;
const toIndex = snapPoints.indexOf(toPoint);

if (toIndex !== animatedCurrentIndex.value) {
_providedOnAnimate(animatedCurrentIndex.value, toIndex);
}
Expand Down Expand Up @@ -1268,12 +1254,12 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
animatedScrollableState,
animatedKeyboardState,
animatedScrollableType,
animatedKeyboardHeight,
animatedIndex,
animatedPosition,
animatedContentHeight,
animatedHandleHeight,
animatedFooterHeight,
animatedKeyboardHeight,
animatedContainerHeight,
scrollableContentOffsetY,
isInTemporaryPosition,
Expand All @@ -1286,8 +1272,8 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
activeOffsetY: _providedActiveOffsetY,
failOffsetX: _providedFailOffsetX,
failOffsetY: _providedFailOffsetY,
contentPanGestureHandler,
getKeyboardHeightInContainer,
contentPanGestureHandler,
setScrollableRef,
removeScrollableRef,
}),
Expand All @@ -1296,17 +1282,13 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
animatedPosition,
animatedContentHeight,
animatedScrollableType,
getKeyboardHeightInContainer,
animatedFooterHeight,
animatedContainerHeight,
animatedHandleHeight,
animatedAnimationState,
animatedKeyboardState,
animatedKeyboardHeight,
animatedSheetState,
contentPanGestureHandler,
setScrollableRef,
removeScrollableRef,
shouldHandleKeyboardEvents,
animatedScrollableState,
scrollableContentOffsetY,
Expand All @@ -1320,6 +1302,10 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
_providedActiveOffsetY,
_providedFailOffsetX,
_providedFailOffsetY,
getKeyboardHeightInContainer,
contentPanGestureHandler,
setScrollableRef,
removeScrollableRef,
]
);
const externalContextVariables = useMemo(
Expand Down Expand Up @@ -1368,7 +1354,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
return {
height: animate(animatedContentHeight.value, _providedAnimationConfigs),
};
}, [_providedContentHeight]);
}, [animatedContentHeight, _providedContentHeight]);
const contentContainerStyle = useMemo(
() => [styles.contentContainer, contentContainerAnimatedStyle],
[contentContainerAnimatedStyle]
Expand Down Expand Up @@ -1477,8 +1463,11 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
component: BottomSheet.name,
method: 'useAnimatedReaction::OnSnapPointChange',
params: {
animatedSnapPoints: _animatedSnapPoints,
prev: _previousAnimatedSnapPoints,
// animatedSnapPoints: _animatedSnapPoints,
// prev: _previousAnimatedSnapPoints,
animatedPosition: animatedPosition.value,
animatedNextPosition: animatedNextPosition.value,
animatedNextPositionIndex: animatedNextPositionIndex.value,
animatedCurrentIndex: animatedCurrentIndex.value,
},
});
Expand All @@ -1489,8 +1478,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
* if snap points changed while sheet is animating, then
* we stop the animation and animate to the updated point.
*/
if (animatedPosition.value !== animatedNextPosition.value) {
cancelAnimation(animatedPosition);
if (animatedAnimationState.value === ANIMATION_STATE.RUNNING) {
nextPosition =
animatedNextPositionIndex.value !== -1
? _animatedSnapPoints[animatedNextPositionIndex.value]
Expand Down
3 changes: 0 additions & 3 deletions src/components/bottomSheet/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import Animated, { Easing } from 'react-native-reanimated';
import {
KEYBOARD_BEHAVIOR,
KEYBOARD_BLUR_BEHAVIOR,
KEYBOARD_INPUT_MODE,
WINDOW_HEIGHT,
} from '../../constants';
import { exp } from '../../utilities/easingExp';
Expand All @@ -28,7 +27,6 @@ const DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE = false;
const DEFAULT_ANIMATE_ON_MOUNT = false;
const DEFAULT_KEYBOARD_BEHAVIOR = KEYBOARD_BEHAVIOR.none;
const DEFAULT_KEYBOARD_BLUR_BEHAVIOR = KEYBOARD_BLUR_BEHAVIOR.none;
const DEFAULT_KEYBOARD_INPUT_MODE = KEYBOARD_INPUT_MODE.adjustPan;

// initial values
const INITIAL_SNAP_POINT = -999;
Expand All @@ -55,7 +53,6 @@ export {
DEFAULT_ANIMATE_ON_MOUNT,
DEFAULT_KEYBOARD_BEHAVIOR,
DEFAULT_KEYBOARD_BLUR_BEHAVIOR,
DEFAULT_KEYBOARD_INPUT_MODE,
// initial
INITIAL_POSITION,
INITIAL_CONTAINER_HEIGHT,
Expand Down
8 changes: 0 additions & 8 deletions src/components/bottomSheet/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type { BottomSheetBackgroundProps } from '../bottomSheetBackground';
import type {
KEYBOARD_BEHAVIOR,
KEYBOARD_BLUR_BEHAVIOR,
KEYBOARD_INPUT_MODE,
} from '../../constants';

export interface BottomSheetProps
Expand Down Expand Up @@ -153,13 +152,6 @@ export interface BottomSheetProps
* - `restore`: restore sheet position.
*/
keyboardBlurBehavior?: keyof typeof KEYBOARD_BLUR_BEHAVIOR;
/**
* Defines keyboard input mode for Android only.
* @link {https://developer.android.com/guide/topics/manifest/activity-element#wsoft}
* @type `adjustPan` | `adjustResize`
* @default `adjustPan`
*/
android_keyboardInputMode?: keyof typeof KEYBOARD_INPUT_MODE;
//#endregion

/**
Expand Down
Loading

0 comments on commit 2d74ab0

Please sign in to comment.