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

Incompatibility with React Navigation Native Stack: causes content to be placed under the app bar on Android

Open l-barbosa opened this issue 3 years ago • 11 comments

Description

When using layout animations in a tabbed/stack view combination using react-navigation's NativeStack (a fairly common use case), once an animation occurs it will cause the content on top of the screen to be hidden behind the app bar on Android. All tabs that weren't open before the animation occurred, once opened, will also show this behavior.

Expected behavior

The content should not be hidden by the app bar

Actual behavior & steps to reproduce

Once the layout animation occurs, the app bar on the native stack navigator where the animation is will hide the top of the content. Any tab that has not been opened before the animation occurred, when opened, will show the same issue.

tapping animated tab first and then "other tab" opening "other tab" first and then animated tab

Snack or minimal code example

Demo repository here

The relevant code is this:

import 'react-native-gesture-handler';
import * as React from 'react';
import {StyleSheet, Text, View} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import Animated, {BounceIn, BounceOut} from 'react-native-reanimated';

const styles = StyleSheet.create({
  bigText: {
    fontSize: 30,
  },
});

function NormalScreen() {
  return (
    <View>
      <Text style={styles.bigText}>This is a screen without animation.</Text>
    </View>
  );
}
function AnimatedScreen() {
  return (
    <View>
      <Animated.Text
        entering={BounceIn}
        exiting={BounceOut}
        style={styles.bigText}>
        {`Screen with layout animation. Opening this screen will move the content below the app bar.
If this tab is viewed before the "OtherTab", switching to that tab will also show its content under the app bar.
If "OtherTab" is opened first, then only this tab will have the issue.
Once the issue happens, only restarting the app returns it to normal.
        `}
      </Animated.Text>
    </View>
  );
}
const HomeStack = createNativeStackNavigator();
function HomeStackScreen() {
  return (
    <HomeStack.Navigator>
      <HomeStack.Screen name="Home" component={NormalScreen} />
    </HomeStack.Navigator>
  );
}
const AnotherTabStack = createNativeStackNavigator();
function AnotherTabStackScreen() {
  return (
    <AnotherTabStack.Navigator>
      <AnotherTabStack.Screen name="Another" component={NormalScreen} />
    </AnotherTabStack.Navigator>
  );
}

const AnimatedTabStack = createNativeStackNavigator();
function AnimatedTabStackScreen() {
  return (
    <AnimatedTabStack.Navigator>
      <AnimatedTabStack.Screen name="Animated" component={AnimatedScreen} />
    </AnimatedTabStack.Navigator>
  );
}

const Tab = createBottomTabNavigator();
export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator screenOptions={{headerShown: false}}>
        <Tab.Screen name="HomeTab" component={HomeStackScreen} />
        <Tab.Screen name="AnimatedTab" component={AnimatedTabStackScreen} />
        <Tab.Screen name="OtherTab" component={AnotherTabStackScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Package versions

name version
react-native 0.69.1
react-native-reanimated ^2.9.1
@react-navigation/stack ^6.2.2
@react-navigation/native-stack ^6.7.0
@react-navigation/native ^6.0.11
@react-navigation/bottom-tabs ^6.3.2

Affected platforms

  • [ x ] Android
  • [ ] iOS
  • [ ] Web

l-barbosa avatar Jul 06 '22 18:07 l-barbosa

this is caused by the layout animation.

ddikodroid avatar Jul 11 '22 07:07 ddikodroid

this is caused by the layout animation.

That is correct. Once the entering/exiting animations are removed the issue stops occurring.

l-barbosa avatar Jul 11 '22 10:07 l-barbosa

this is caused by the layout animation.

That is correct. Once the entering/exiting animations are removed the issue stops occurring.

yes, the layout animation makes component doesn't unmount correctly

ddikodroid avatar Jul 11 '22 13:07 ddikodroid

Its currently undergoing a rewrite, might be fixed soon

hirbod avatar Jul 12 '22 21:07 hirbod

Yeah, facing a similar issue. Using it in the header

quicksilverr avatar Jul 15 '22 11:07 quicksilverr

Yep same here, if we add <Animated.View layout={CurvedTransition}> within a screen then the header overlaps the children of the screen

image

walterholohan avatar Jul 28 '22 13:07 walterholohan

I don't even need layout prop. Just adding Animated.View on the screen causes the issue. It gets worse when using ScrollView and TextInput together. (flickering)

CleanShot 2022-08-23 at 16 32 00

export default function NotFoundScreen({ navigation }: RootStackScreenProps<'NotFound'>) {
  return (
    <ScrollView contentContainerStyle={styles.container}>
      <Text style={styles.title}>Title 1</Text>
      <Text style={styles.title}>Title 2</Text>
      <Text style={styles.title}>Title 3</Text>
      <Text style={styles.title}>Title 4</Text>
      <Text style={styles.title}>Title 5</Text>
      <Animated.View>
        <Image source={require('../assets/images/favicon.png')} />
      </Animated.View>
      <TextInput style={styles.input} />
      <TouchableOpacity onPress={() => navigation.push('NotFound')} style={styles.link}>
        <Text style={styles.linkText}>Next screen!</Text>
      </TouchableOpacity>
    </ScrollView>
  );
}

IngyuTae avatar Aug 23 '22 07:08 IngyuTae

I don't even need layout prop. Just adding Animated.View on the screen causes the issue. It gets worse when using ScrollView and TextInput together. (flickering)

CleanShot 2022-08-23 at 16 32 00 CleanShot 2022-08-23 at 16 32 00

export default function NotFoundScreen({ navigation }: RootStackScreenProps<'NotFound'>) {
  return (
    <ScrollView contentContainerStyle={styles.container}>
      <Text style={styles.title}>Title 1</Text>
      <Text style={styles.title}>Title 2</Text>
      <Text style={styles.title}>Title 3</Text>
      <Text style={styles.title}>Title 4</Text>
      <Text style={styles.title}>Title 5</Text>
      <Animated.View>
        <Image source={require('../assets/images/favicon.png')} />
      </Animated.View>
      <TextInput style={styles.input} />
      <TouchableOpacity onPress={() => navigation.push('NotFound')} style={styles.link}>
        <Text style={styles.linkText}>Next screen!</Text>
      </TouchableOpacity>
    </ScrollView>
  );
}

facing the same issue right now, don't have any LayoutAnimation and the component didn't unmount

ddikodroid avatar Aug 24 '22 03:08 ddikodroid

We're also running into this issue. We have an entering and exiting animation and as soon as it runs once, all screens that have a tabbed header within the stack overlap their content. On iOS, the library works FANTASTIC, but this is unfortunately a blocker for our Android implementation.

conoremclaughlin avatar Sep 20 '22 05:09 conoremclaughlin

Seeing this too

nschild avatar Sep 23 '22 21:09 nschild

The same issue here. Animated.View component does nothing wrong, but as soon as I include entering or exiting prop the header covers the top content of the screen.

stachu2k avatar Oct 03 '22 11:10 stachu2k

surprisingly this only happens with NativeStack headers and not with things linke BottomNavigation headers

/cc @satya164 I'm not sure if this is an issue in reanimated or with NativeStack. What do you think?

forki avatar Oct 13 '22 12:10 forki

This bug was very difficult to figure out 🐒 Trying to refactor out Moti and finding out that it would break the navigation header by doing:

import * as Reanimated from 'react-native-reanimated'
...
<Reanimated.default.View entering={Reanimated.FadeIn}>

@hirbod is there any status on this?

Norfeldt avatar Oct 18 '22 13:10 Norfeldt

I'm having the same issue here.

winterdouglas avatar Oct 27 '22 07:10 winterdouglas

Will this be fixed soon? The library is unusable right now.

djordjejanjic avatar Nov 04 '22 09:11 djordjejanjic

@piaskowyk cool thanks for fixing this!

forki avatar Jan 05 '23 10:01 forki