Skip to content

Android: useAnimatedKeyboard listener breaks translucent StatusBar + NavigationBar #3631

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ChildishForces opened this issue Sep 30, 2022 · 7 comments · Fixed by #3958
Closed
Labels
Needs review Issue is ready to be reviewed by a maintainer Platform: Android This issue is specific to Android Repro provided A reproduction with a snippet of code, snack or repo is provided

Comments

@ChildishForces
Copy link

ChildishForces commented Sep 30, 2022

Description

When using useAnimatedKeyboard applications that take advantage of the full screen by using translucent (absolutely positioned) StatusBar and NavigationBar revert to having solid counterparts. (Full reproduction repo below, no need to follow the steps)

Steps to reproduce

  1. Instantiate a React Native project.
  2. Create the following methods in MainActivity.java:
  private void transparentStatusAndNavigation() {
      //make full transparent statusBar
      if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
          setWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                  | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, true);
      }
      if (Build.VERSION.SDK_INT >= 19) {
          getWindow().getDecorView().setSystemUiVisibility(
                  View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                          | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                          | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
          );
      }
      if (Build.VERSION.SDK_INT >= 21) {
          setWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                  | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, false);
          getWindow().setStatusBarColor(Color.TRANSPARENT);
          getWindow().setNavigationBarColor(Color.TRANSPARENT);
      }
  }

  private void setWindowFlag(final int bits, boolean on) {
      Window win = getWindow();
      WindowManager.LayoutParams winParams = win.getAttributes();
      if (on) {
          winParams.flags |= bits;
      } else {
          winParams.flags &= ~bits;
      }
      win.setAttributes(winParams);
  }
  1. Call from onCreate:
@Override
protected void onCreate(Bundle savedInstanceState) {
  // Rest of logic here
  transparentStatusAndNavigation();
}
  1. Remember to add new imports:
import android.graphics.Color;
import android.view.Window;
import android.view.WindowManager;
import android.view.View;
  1. Use useAnimatedKeyboard and the insets will disappear.

Snack or a link to a repository

https://github.com/ChildishForces/reanimated-bug-repro

Reanimated version

2.10.0

React Native version

0.69.0

Platforms

Android

JavaScript runtime

Hermes

Workflow

Expo bare workflow

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

Real device

Device model

OnePlus 9 Pro

Acknowledgements

Yes

@ChildishForces ChildishForces added the Needs review Issue is ready to be reviewed by a maintainer label Sep 30, 2022
@github-actions github-actions bot added Repro provided A reproduction with a snippet of code, snack or repo is provided Platform: Android This issue is specific to Android labels Sep 30, 2022
@ChildishForces
Copy link
Author

ChildishForces commented Oct 3, 2022

FYI: From my basic investigation I think the following lines may be the culprit

I tried to clone, fix and build, but I think there is something different about the build process of 2.10.0 where remote sources/binaries are included. If someone were to explain how to disable this to me, I'd be happy to implement a check to store the initial value and return it to that, rather than true, and submit a PR.

@hirbod
Copy link
Contributor

hirbod commented Oct 6, 2022

There are many things connected to this.

Are you using expo or expo-dev-client? Are you using react-native-screens and the native stack? If so, make sure you're at minimum version 3.14+. There are still some cases were the old deprecated window flag manipulation is used (even in core react-native). This breaks every usage of the Windows Insets API.

I am using https://github.com/kirillzyusko/react-native-keyboard-controller, which provides basically the same hook. @kirillzyusko and I spent a ton of time to track down this issues and his library also exposes a statusBarTranslucent prop on the provider to fix all of this weird issues. You could give it a try.

@ChildishForces
Copy link
Author

ChildishForces commented Oct 10, 2022

I'll do that and report back, though would love to see this resolved in reanimated, as I like to keep my dependencies as few as possible.

@ChildishForces
Copy link
Author

@hirbod Sorry, forgot to update! Your provided solution worked perfectly, thanks for your help. Going to leave this issue open, so when the RNR team get round to it they have a summary & repro of the issue for their own hook.

@alexco2
Copy link

alexco2 commented Nov 1, 2022

I have the same bug. Here is a reproducible code snippet. I'm using the latest RN (0.70.4) and reanimated (2.12.0)

import React from 'react';
import {Button, View, StyleSheet, StatusBar} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';

import {useAnimatedKeyboard} from 'react-native-reanimated';

function HomeScreen({navigation}) {
  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: 'green',
      }}>
      <Button
        title="Go to Profile"
        onPress={() => navigation.navigate('Notifications')}
      />
    </View>
  );
}

function NotificationsScreen({navigation}) {
  const keyboard = useAnimatedKeyboard(); // <=====
  return (
      <View
        style={{
          flex: 1,
          alignItems: 'center',
          justifyContent: 'center',
          backgroundColor: 'blue',
        }}>
        <Button title="Go back" onPress={() => navigation.goBack()} />
      </View>
  );
}

const Stack = createNativeStackNavigator();

function MyStack() {
  return (
    <Stack.Navigator screenOptions={{headerShown: false}}>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Notifications" component={NotificationsScreen} />
    </Stack.Navigator>
  );
}

export default function App() {
  return (
    <GestureHandlerRootView style={{flex: 1, backgroundColor: 'red'}}>
      <StatusBar
        barStyle="dark-content"
        hidden={false}
        translucent={true}
        backgroundColor="transparent"
      />
      <NavigationContainer>
        <MyStack />
      </NavigationContainer>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    backgroundColor: 'blue',
  },
  contentContainer: {
    flex: 1,
    alignItems: 'center',
  },
});

@piaskowyk
Copy link
Member

Hey, could someone confirm if this PR - #3958 fix the problem?

piaskowyk pushed a commit that referenced this issue Jan 17, 2023
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

Fixes
#3631
Fixes the issue with translucent StatusBar on Android by adding the
option `isStatusBarTranslucentAndroid` in `useAnimatedKeyboard`. It is
the same solution as the one mentioned in the issue:
kirillzyusko/react-native-keyboard-controller@2a7c92f

## Test plan

There is an excellent example in the issue that reproduces the problem:
https://github.com/ChildishForces/reanimated-bug-repro
I tested on real Android device with Android 12 and RN 71.
I think it would be nice to also test on RN < 70 because the bottom
padding may behave differently.
@peterlazar1993
Copy link

@piaskowyk I don't think this PR completely fixed the issue. For more info please see the bug report here #4277 .

fluiddot pushed a commit to wordpress-mobile/react-native-reanimated that referenced this issue Jun 5, 2023
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

Fixes
software-mansion#3631
Fixes the issue with translucent StatusBar on Android by adding the
option `isStatusBarTranslucentAndroid` in `useAnimatedKeyboard`. It is
the same solution as the one mentioned in the issue:
kirillzyusko/react-native-keyboard-controller@2a7c92f

## Test plan

There is an excellent example in the issue that reproduces the problem:
https://github.com/ChildishForces/reanimated-bug-repro
I tested on real Android device with Android 12 and RN 71.
I think it would be nice to also test on RN < 70 because the bottom
padding may behave differently.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs review Issue is ready to be reviewed by a maintainer Platform: Android This issue is specific to Android Repro provided A reproduction with a snippet of code, snack or repo is provided
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants