diff --git a/android/src/main/java/com/swmansion/reanimated/keyboard/Keyboard.java b/android/src/main/java/com/swmansion/reanimated/keyboard/Keyboard.java
index 0f8ae78071e..d71bd5f0725 100644
--- a/android/src/main/java/com/swmansion/reanimated/keyboard/Keyboard.java
+++ b/android/src/main/java/com/swmansion/reanimated/keyboard/Keyboard.java
@@ -1,7 +1,5 @@
package com.swmansion.reanimated.keyboard;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
import androidx.core.view.WindowInsetsCompat;
import com.facebook.react.uimanager.PixelUtil;
@@ -23,9 +21,7 @@ public int getHeight() {
public void updateHeight(WindowInsetsCompat insets) {
int contentBottomInset = insets.getInsets(CONTENT_TYPE_MASK).bottom;
int systemBarBottomInset = insets.getInsets(SYSTEM_BAR_TYPE_MASK).bottom;
- boolean hasNavigationBar = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);
- int keyboardHeightDip =
- hasNavigationBar ? contentBottomInset - systemBarBottomInset : contentBottomInset;
+ int keyboardHeightDip = contentBottomInset - systemBarBottomInset;
int keyboardHeight = (int) PixelUtil.toDIPFromPixel(Math.max(0, keyboardHeightDip));
if (keyboardHeight == 0 && mState == KeyboardState.OPEN) {
/*
@@ -35,7 +31,7 @@ public void updateHeight(WindowInsetsCompat insets) {
*/
return;
}
- mHeight = (int) PixelUtil.toDIPFromPixel(keyboardHeightDip);
+ mHeight = keyboardHeight;
}
public void onAnimationStart() {
diff --git a/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java b/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java
index b7ad125e9c8..353084cf042 100644
--- a/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java
+++ b/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java
@@ -9,7 +9,6 @@
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import com.facebook.react.bridge.ReactApplicationContext;
-import com.swmansion.reanimated.BuildConfig;
import java.lang.ref.WeakReference;
public class WindowsInsetsManager {
@@ -58,24 +57,19 @@ private void updateWindowDecor(boolean decorFitsSystemWindow) {
}
private WindowInsetsCompat onApplyWindowInsetsListener(View view, WindowInsetsCompat insets) {
+ WindowInsetsCompat defaultInsets = ViewCompat.onApplyWindowInsets(view, insets);
if (mKeyboard.getState() == KeyboardState.OPEN) {
mKeyboard.updateHeight(insets);
mNotifyAboutKeyboardChange.call();
}
- setWindowInsets(insets);
- return insets;
+ setWindowInsets(defaultInsets);
+ return defaultInsets;
}
private void setWindowInsets(WindowInsetsCompat insets) {
- int paddingBottom = 0;
- boolean isOldPaperImplementation =
- !BuildConfig.IS_NEW_ARCHITECTURE_ENABLED && BuildConfig.REACT_NATIVE_MINOR_VERSION < 70;
- if (isOldPaperImplementation) {
- int navigationBarTypeMask = WindowInsetsCompat.Type.navigationBars();
- paddingBottom = insets.getInsets(navigationBarTypeMask).bottom;
- }
int systemBarsTypeMask = WindowInsetsCompat.Type.systemBars();
int paddingTop = insets.getInsets(systemBarsTypeMask).top;
+ int paddingBottom = insets.getInsets(systemBarsTypeMask).bottom;
updateInsets(paddingTop, paddingBottom);
}
@@ -95,7 +89,7 @@ private FrameLayout.LayoutParams getLayoutParams(int paddingTop, int paddingBott
FrameLayout.LayoutParams params =
new FrameLayout.LayoutParams(matchParentFlag, matchParentFlag);
if (mIsStatusBarTranslucent) {
- params.setMargins(0, 0, 0, 0);
+ params.setMargins(0, 0, 0, paddingBottom);
} else {
params.setMargins(0, paddingTop, 0, paddingBottom);
}
diff --git a/docs/docs/device/useAnimatedKeyboard.mdx b/docs/docs/device/useAnimatedKeyboard.mdx
index d337062a4c0..0a723f0c52e 100644
--- a/docs/docs/device/useAnimatedKeyboard.mdx
+++ b/docs/docs/device/useAnimatedKeyboard.mdx
@@ -2,72 +2,119 @@
sidebar_position: 1
---
-:::info
-This page was ported from an old version of the documentation.
-
-As we're rewriting the documentation some of the pages might be a little outdated.
-:::
+`useAnimatedKeyboard` lets you create animations based on state and height of the virtual keyboard.
:::caution
-Android implementation of `useAnimatedKeyboard` is an experimental feature.
+Android implementation of `useAnimatedKeyboard` has drawbacks on Android SDK < 30, for more details see [remarks](/docs/device/useAnimatedKeyboard#remarks) section.
:::
-With the `useAnimatedKeyboard` hook, you can create animations based on current keyboard position.
+## Reference
+
+```javascript
+import { useAnimatedKeyboard, useAnimatedStyle } from 'react-native-reanimated';
+
+export default function App() {
+ const keyboard = useAnimatedKeyboard();
+
+ const animatedStyles = useAnimatedStyle(() => ({
+ transform: [{ translateY: -keyboard.height.value }],
+ }));
+}
+```
+
+
+Type definitions
+
+```typescript
+// --- Function declaration ---
+
+function useAnimatedKeyboard(
+ options: AnimatedKeyboardOptions
+): AnimatedKeyboardInfo;
+
+// --- Configuration types ---
+
+export interface AnimatedKeyboardOptions {
+ isStatusBarTranslucentAndroid?: boolean;
+}
+
+// --- Return types ---
-On Android, make sure to set `android:windowSoftInputMode` in your `AndroidManifest.xml` to `adjustResize`. Then, using the `useAnimatedKeyboard` hook disables
-the default Android behavior (resizing the view to accommodate keyboard) in the whole app. Using values from `useAnimatedKeyboard` hook you can handle the keyboard yourself. Unmounting all components that use `useAnimatedKeyboard` hook brings back the default Android behavior.
+export type AnimatedKeyboardInfo = {
+ height: SharedValue;
+ state: SharedValue;
+};
+
+export enum KeyboardState {
+ UNKNOWN = 0,
+ OPENING = 1,
+ OPEN = 2,
+ CLOSING = 3,
+ CLOSED = 4,
+}
+```
+
+
### Arguments
-#### `options` [AnimatedKeyboardOptions]
+#### `options`
-Optional object containing additional configuration.
+Optional object containing additional configuration:
+
+- `isStatusBarTranslucentAndroid` - removes top inset on Android i.e. to use translucent status bar on Android, set this option to `true`. Defaults to `false`. Ignored on iOS.
### Returns
-Hook `useAnimatedKeyboard` returns an instance of [[AnimatedKeyboardInfo](#animatedkeyboard-object)];
+Hook `useAnimatedKeyboard` returns an object containing these fields:
-### Types
+| Name | Type | Description |
+| ------ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| height | `SharedValue` | A [shared value](/docs/fundamentals/glossary#shared-value) containing current height of the keyboard. |
+| state | `SharedValue` | A [shared value](/docs/fundamentals/glossary#shared-value) containing current state of the keyboard. Possible states: `{ CLOSED, OPEN, CLOSING, OPENING }` |
-#### `AnimatedKeyboardInfo: [object]`
+## Example
-Properties:
+import useBaseUrl from '@docusaurus/useBaseUrl';
+import AnimatedKeyboardSrc from '!!raw-loader!@site/src/examples/AnimatedKeyboard';
-- `height`: [[SharedValue](/docs/core/useSharedValue)] contains `[number]`
- contains current height of the keyboard
-- `state`: [[SharedValue](/docs/core/useSharedValue)] contains `[enum]`
- contains current state of the keyboard. Possible states: `{ CLOSED, OPEN, CLOSING, OPENING }`
+
+ }
+/>
-#### `AnimatedKeyboardOptions: [object]`
+## Remarks
-Properties:
+- On Android, make sure to set `android:windowSoftInputMode` in your `AndroidManifest.xml` to `adjustResize`. Then, using the `useAnimatedKeyboard` hook disables
+ the default Android behavior (resizing the view to accommodate keyboard) in the whole app. Using values from `useAnimatedKeyboard` hook you can handle the keyboard yourself. Unmounting all components that use `useAnimatedKeyboard` hook brings back the default Android behavior.
-- `isStatusBarTranslucentAndroid`[bool] - if you want to use translucent status bar on Android, set this option to `true`. Defaults to `false`. Ignored on iOS.
+- On Android, using the `useAnimatedKeyboard` hook expands root view to full screen ([immersive mode](https://developer.android.com/develop/ui/views/layout/immersive)) and takes control over insets management.
-### Example
+ - When `isStatusBarTranslucentAndroid` is `false` it applies the top and bottom margins according to the insets.
-```jsx
-function AnimatedKeyboardExample() {
- const keyboard = useAnimatedKeyboard();
- const translateStyle = useAnimatedStyle(() => {
- return {
- transform: [{ translateY: -keyboard.height.value }],
- };
- });
-
- return (
-
-
-
-
-
- );
-}
-```
+ - When `isStatusBarTranslucentAndroid` is `true` it applies bottom padding according to the navigation inset and sets top margin to `0`.
+
+- On Android, when using navigation with native header, `isStatusBarTranslucentAndroid` doesn't affect the top inset.
+
+- On Android SDK < 30, when status bar is hidden, the keyboard reverts to the default Android behavior.
+
+## Platform compatibility
+
+