react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

useAnimatedKeyboard causes navigation bar jump with React Navigation on Android

Open alexmngn opened this issue 11 months ago • 8 comments

Description

My navigation bar unexpectedly jumps or shifts when transitioning to a screen implementing useAnimatedKeyboard on Android. This issue disappears when the hook is removed.

Video demo

With useAnimatedKeyboard

https://github.com/user-attachments/assets/b5845fbe-60db-4fa5-a9e0-1fc2f53276d8

Without useAnimatedKeyboard

https://github.com/user-attachments/assets/c1480f5c-3ea7-4503-84ef-268273544686

The only code change between those 2 videos was removing this line in the screen I transitioned to.

const keyboard = useAnimatedKeyboard();

I was able to reproduce the issue on a real device as well as on an Android emulator.

Steps to reproduce

1. Set up a project with React Navigation and Reanimated.
2. Add useAnimatedKeyboard to a component
3. Run the app and navigate to the screen implementing the hook.

Snack or a link to a repository

https://snack.expo.dev/@alexmngn/supportive-yellow-watermelon

Reanimated version

3.16.7

React Native version

0.75.4

React Navigation version

7.0.14

Platforms

Android

JavaScript runtime

Hermes

Workflow

React Native

Architecture

Paper (Old Architecture)

Build type

Debug app & dev bundle

Device

Android emulator Real device

Device model

Galaxy A22

Acknowledgements

Yes

alexmngn avatar Jan 16 '25 11:01 alexmngn

I'm running into this same issue, though I'm not using headers in my pages.

It's also causing a weird interaction with a basic SafeAreaWrapper component I have, where it adds a small, blank, "header" at the top of my screen maybe 25 pixels tall. I'm assuming it's the same height as the status bar, as that's part of my SafeAreaWrapper component, but this blank bar only appears in components that use useAnimatedKeyboard. It's the color that I define as the background color in my theme object on the NavigationContainer component from React Navigation.

I've looked into the code for useAnimatedKeyboard a bit but haven't had any luck determining what the issue might be

dallasmay avatar Feb 07 '25 01:02 dallasmay

I too have issues with useAnimatedKeyboard on Android. This patch solved it for me

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 5660944825836f4f79d82876773c58ca3a4a1368..a0cbe7be5472b872a4afcb256dcc0dcdc2314f55 100644
--- a/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java
+++ b/android/src/main/java/com/swmansion/reanimated/keyboard/WindowsInsetsManager.java
@@ -56,7 +56,6 @@ public class WindowsInsetsManager {
 
   public void stopObservingChanges() {
     updateWindowDecor(!mIsStatusBarTranslucent && !mIsNavigationBarTranslucent);
-    updateInsets(0, 0);
 
     Activity currentActivity = getCurrentActivity();
     if (currentActivity == null) {

mysport12 avatar Feb 25 '25 20:02 mysport12

I face the same issue and solve it by using useAnimatedKeyboard() hook at the global or upper level in my app

vule24 avatar Mar 09 '25 15:03 vule24

I face the same issue +

V-Babayan avatar Apr 24 '25 11:04 V-Babayan

I face the same issue and solve it by using useAnimatedKeyboard() hook at the global or upper level in my app

goat

Pnlvfx avatar Jun 12 '25 00:06 Pnlvfx

same issue +1

hangaoke1 avatar Jun 16 '25 05:06 hangaoke1

same issue +

hectorminayat avatar Jun 24 '25 00:06 hectorminayat

same

kshitij-khowal avatar Jun 24 '25 11:06 kshitij-khowal

@alexmngn hey! Despite not having translucency, adding the following properties to useAnimatedKeyboard solved the issue. I believe it is related to expo router's internal stuff. Could you try it?

{
  isStatusBarTranslucentAndroid: true,
  isNavigationBarTranslucentAndroid: true
}

akbarnurullaev avatar Jul 12 '25 08:07 akbarnurullaev

+1 problem is with devices that dont have safeAreaInsets.

I started using it since default Keyboard API cannot detect ribbons (emoji, suggestions...) on Samsung devices with Samsung keyboard since those ribbons are not mounted with keyboard.

So this one works, but flicker is annoying on devices with top/bottom inset 0. I have even condition that but I can still see it:

  const {height} = useAnimatedKeyboard({
    isStatusBarTranslucentAndroid: safeAreaInsets.top > 0,
    isNavigationBarTranslucentAndroid: safeAreaInsets.bottom > 0,
  });

problem happens even if I dont use height anywhere.

cveklica avatar Sep 05 '25 07:09 cveklica

Reason
When switching screens (e.g., Screen1 → Screen2), if every component using useAnimatedKeyboard() unmounts even briefly, Android falls back to its default keyboard-resize behavior. When the next screen mounts and the hook subscribes again, Reanimated takes back control—resulting in a visible jump/flicker. In this case, Screen1 uses the default resize, and when Screen2 mounts, useAnimatedKeyboard() takes over, causing the flicker.

Fix
Mount a tiny component at the app root that only calls useAnimatedKeyboard() once. This keeps at least one subscriber alive across stack swaps. The rest of your app can keep using useAnimatedKeyboard() as usual — no changes required.

// KeyboardKeeper.tsx
import React from 'react';
import { useAnimatedKeyboard } from 'react-native-reanimated';

// Keeps a global subscription so Android doesn't flip behaviors during screen swaps.
export function KeyboardKeeper({ children }: React.PropsWithChildren) {
  useAnimatedKeyboard(); // single, app-wide subscription
  return <>{children}</>;
}
// App.tsx (root)
import { NavigationContainer } from '@react-navigation/native';
import { KeyboardKeeper } from './KeyboardKeeper';

export default function App() {
  return (
    <KeyboardKeeper>
      <NavigationContainer>
        ... app stack
      </NavigationContainer>
    </KeyboardKeeper>
  );
}

Grassper avatar Sep 27 '25 08:09 Grassper