Skip to content
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

useAnimatedKeyboard break navigation color #6043

Closed
RohovDmytro opened this issue May 23, 2024 · 13 comments · Fixed by #6431
Closed

useAnimatedKeyboard break navigation color #6043

RohovDmytro opened this issue May 23, 2024 · 13 comments · Fixed by #6431
Labels
Missing info The user didn't precise the problem enough Platform: Android This issue is specific to Android Repro provided A reproduction with a snippet of code, snack or repo is provided

Comments

@RohovDmytro
Copy link

RohovDmytro commented May 23, 2024

Description

After upgrading to the latest version with expo@51 when I use keyboardInfoAnimated inside of a modal I've started observing changes in the color of bottom navigation on Android.

  • Android 14
  • Gesture Navigation enabled

Steps to reproduce

  1. use keyboardInfoAnimated from inside of a modal
const keyboardInfoAnimated = useAnimatedKeyboard({
    isStatusBarTranslucentAndroid: true,
  });

Snack or a link to a repository

Reanimated version

3.11.0

React Native version

0.74.1

Platforms

Android

JavaScript runtime

None

Workflow

None

Architecture

None

Build type

None

Device

None

Device model

No response

Acknowledgements

Yes

@github-actions github-actions bot added Missing repro This issue need minimum repro scenario Missing info The user didn't precise the problem enough labels May 23, 2024
Copy link

github-actions bot commented May 23, 2024

Hey! 👋

It looks like you've omitted a few important sections from the issue template.

Please complete Snack or a link to a repository section.

@github-actions github-actions bot added the Platform: Android This issue is specific to Android label May 23, 2024
@RohovDmytro
Copy link
Author

RohovDmytro commented May 23, 2024

This might also be relevant, these are the settings of the nav bar:

['expo-navigation-bar', {
    "position": "absolute",
    "backgroundColor": BACKGROUND_COLOR,
    "borderColor": '#00000000',
    "barStyle": "light"
  }]

@RohovDmytro
Copy link
Author

bottom inset from useSafeAreaInsets is 24 when I render modal without keyboard height listener, and 0 when I can that hook.

@maciekstosio
Copy link
Contributor

maciekstosio commented May 27, 2024

Hi, could you provide a snack or repo with reproduction and some steps or video what's the issue? At this point, I'm not sure.

bottom inset from useSafeAreaInsets is 24 when I render modal without keyboard height listener, and 0 when I can that hook.

But does this cause any problems for you? It's is possible that it changes - we turn immersive mode to listen to keyboard changes and apply margins to compensate for that.

@computerjazz
Copy link

computerjazz commented Jun 28, 2024

@maciekstosio I can confirm including useAnimatedKeyboard anywhere in the app causes a transparent navigation bar to render white. Snack here: https://snack.expo.dev/@easydan/android-navigation-bar-color-bug

Repro steps:

  • create snack with transparent navbar
  • launch snack on android emulator (or android device)
  • background snack
  • go to Settings -> System -> Gestures -> System Navigation
  • Choose "Gesture Navigation"
  • Return to snack
  • Observe white bottom navbar as a result of useAnimatedKeyboard hook being called

navbar-color-bug

Maybe related to this call?

WindowCompat.setDecorFitsSystemWindows(
currentActivity.getWindow(), decorFitsSystemWindow);
});

seems related: https://stackoverflow.com/questions/64153785/android-11-window-setdecorfitssystemwindow-doesnt-show-screen-behind-status-a

@github-actions github-actions bot added Repro provided A reproduction with a snippet of code, snack or repo is provided and removed Missing repro This issue need minimum repro scenario labels Jun 28, 2024
@computerjazz
Copy link

computerjazz commented Jun 28, 2024

What is the purpose of setWindowInsets(defaultInsets) here:

that seems to be what's causing the issue -- if I update insets to 0 immediately after, the navbar issue goes away, though I'm not sure if this has other side effects:

    if (mKeyboard.getState() == KeyboardState.OPEN) {
      mKeyboard.updateHeight(insets);
      mNotifyAboutKeyboardChange.call();
    }
    setWindowInsets(defaultInsets);
    updateInsets(0, 0); // <-- added this line 

    return defaultInsets;

@maciekstosio
Copy link
Contributor

maciekstosio commented Jul 22, 2024

What is the purpose of setWindowInsets(defaultInsets) here:

that seems to be what's causing the issue -- if I update insets to 0 immediately after, the navbar issue goes away, though I'm not sure if this has other side effects:

    if (mKeyboard.getState() == KeyboardState.OPEN) {
      mKeyboard.updateHeight(insets);
      mNotifyAboutKeyboardChange.call();
    }
    setWindowInsets(defaultInsets);
    updateInsets(0, 0); // <-- added this line 

    return defaultInsets;

Hi, sorry for long delay and thank you for your input. To observe keyboard changes we need updateWindowDecor(false) which expands the view to the edges, but omits insets at the same time. So we get the insets and apply them as padding to compensate for that. When adding the line you proposed when having 3-button navigation, or even gesture navigation but with a background, it will cover visible area. If you're interested in that topic you can take a look at this issue #5851.

I guess this will be the same problem as with status bar where we just have special flag for that - isStatusBarTranslucent. The flag is needed because when you set transparent the insets are there just the background is transparent, and we have no way of observing background change. There is ongoing PR to tackle that #5889, if we won't merge it, I'll probably add a flag isNavigationBarTranslucent to solve this issue.

@maciekstosio
Copy link
Contributor

Btw as a workaround maybe you could use NavigationBar.setVisibilityAsync this method actually hides the navigation bar, thus works well with useAnimatedKeyboard, because the insets change.

@fax1ty
Copy link

fax1ty commented Aug 1, 2024

How can I disable padding of the bottom navigation? I want to fill the whole screen

@maciekstosio
Copy link
Contributor

@computerjazz Hi, I added PR that adds a flag that removes the inset for bottom navigation (#6431), but I'm debugging the "clean up" behavior. Correct me If I'm wrong - when you run your snack without useAnimatedKeyboard the bottom padding exists, am I right? I have a feeling, that it works when commenting out, as a side effect of our clean up logic.

@computerjazz
Copy link

@maciekstosio I think you have it flipped -- when I run the app without useAnimatedKeyboard the background correctly draws behind the nav bar:
Screenshot 2024-08-27 at 9 25 29 AM

When I add useAnimatedKeyboard the area beneath the nav bar turns white, making it impossible to render full-screen content:
Screenshot 2024-08-27 at 9 25 36 AM

@maciekstosio
Copy link
Contributor

@computerjazz Hmm, but is it? I mean on the initial load, not when you build it with useAnimatedKeyboard and then comment out. See the gif below:
Aug-28-2024 16-14-08

@RohovDmytro
Copy link
Author

I've switched into using react-native-keyboard-controller which supports reanimated and it works seamlessly. I especially like it top level provider that enabled the level of controls over top and nav bar appearance.

github-merge-queue bot pushed a commit that referenced this issue Sep 18, 2024
## Summary

Resolves #6043. For StatusBar we have a flag that removes top padding
when we want to render RN stuff "under" StatusBar. A similar problem was
raised in #6043, but for NavigationBar, so I added another flag
`isNavigationBarTranslucentAndroid` that removes bottom padding as well.
Currently, I see no way to make it automatic. I tried one approach to
remove the flags in #5889, but it doesn't seem to be the performant
solution.

## Preview 

|Before|After without flag|After with flag|
|-|-|-|
|<img width="602" alt="before"
src="https://github.com/user-attachments/assets/0032efbe-342a-4e06-81ee-f7351bb032f7">|<img
width="602" alt="after-without-flag"
src="https://github.com/user-attachments/assets/6f259329-9bf4-4bbb-8ce4-32d671e65a5a">|<img
width="602" alt="after-with-flag"
src="https://github.com/user-attachments/assets/81c43052-f3b3-4a3b-a9cb-bd974e851c43">|

## Test plan

Testing is a bit tricky, because an example from the issue uses a
navigation bar package from Expo, which requires Expo and our example
app doesn't have Expo.

What I did:

<details>
<summary>Steps</summary>

```bash
# clone reanimated from current branch 
git clone https://github.com/software-mansion/react-native-reanimated.git
# checkout current branch
git checkout @maciekstosio/Add-support-for-isNavigationBarTranslucentAndroid
# install
yarn && yarn build
# build npm package
cd packages/react-native-reanimated
./createNPMPackage.sh --fresh
# next, create simple expo project
npx create-expo-stack
# install library for navigation bar
npx expo install expo-navigation-bar
# install reanimated 
npx expo install react-native-reanimated
# replace in package.json path to locally-build package i.e.:
"react-native-reanimated": "file:react-native-reanimated.tgz"
# yarn install 
# npx expo run:android
```

</details>

<details>
<summary>App.tsx to test</summary>

```jsx
import * as NavigationBar from 'expo-navigation-bar';
import React, { useEffect } from 'react';
import Animated, {
  useAnimatedKeyboard,
  useAnimatedStyle,
} from 'react-native-reanimated';
import {
  Platform,
  StatusBar,
  StyleSheet,
  TextInput,
  View,
  Text,
  Button,
} from 'react-native';

export default function EmptyExample() {
  const keyboard = useAnimatedKeyboard({
    isNavigationBarTranslucentAndroid: true,
  });

  const animatedStyles = useAnimatedStyle(() => ({
    transform: [{ translateY: -keyboard.height.value }],
  }));

  useEffect(() => {
    StatusBar.setBarStyle('dark-content');
    NavigationBar.setBackgroundColorAsync('transparent');
  }, []);

  return (
    <Animated.View
      style={[
        styles.container,
        animatedStyles,
        { justifyContent: 'flex-end', borderWidth: 5, borderColor: '#ff0' },
      ]}>
      <View
        style={[
          styles.center,
          {
            height: 200,
            backgroundColor: '#f0f',
            borderWidth: 5,
            borderColor: '#0ff',
          },
        ]}>
        <Text>{`Android ${Platform.constants['Release']}`}</Text>
        <TextInput placeholder="Test" />
      </View>
    </Animated.View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: 'rgba(255,0,255,0.2)' },
  center: { justifyContent: 'center', alignItems: 'center' },
});
```

</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Missing info The user didn't precise the problem enough 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.

4 participants