software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.86k stars 1.29k forks source link

Buggy animation using Shared Transition on Android #4235

Open kylegillen opened 1 year ago

kylegillen commented 1 year ago

Description

Using the new Shared Transition API on a new project is causing a jump due to the status bar seemingly not being taken into account when transitioning on Android.

Using React Navigation 6.1.6 with a Native Stack Navigator (6.9.12) and employing a Shared Transition between the screen is causing the glitch shown in the video below:

https://user-images.githubusercontent.com/711457/225827314-86b487cd-e629-44d9-a15f-c8512f2da5cc.mov

Following is the code pasted in the App.tsx file of a new project:

import {Text, Button} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';
import {NavigationContainer} from '@react-navigation/native';
import {
  createNativeStackNavigator,
  NativeStackScreenProps,
} from '@react-navigation/native-stack';
import Animated, {SharedTransition, withSpring} from 'react-native-reanimated';

interface Props {
  text?: string;
}

type RootStackParamList = {
  Home: undefined;
  Detail: undefined;
};

const SPRING_CONFIG = {
  mass: 1,
  stiffness: 200,
  damping: 150,
};

export const sharedElementTransition = SharedTransition.custom(values => {
  'worklet';
  return {
    height: withSpring(values.targetHeight, SPRING_CONFIG),
    width: withSpring(values.targetWidth, SPRING_CONFIG),
    originX: withSpring(values.targetGlobalOriginX, SPRING_CONFIG),
    originY: withSpring(values.targetGlobalOriginY, SPRING_CONFIG),
  };
});

const Stack = createNativeStackNavigator<RootStackParamList>();

const Home = (props: NativeStackScreenProps<RootStackParamList>) => {
  return (
    <SafeAreaView>
      <Text>Home</Text>
      <Animated.View
        sharedTransitionTag="sharedTag"
        sharedTransitionStyle={sharedElementTransition}
        style={{
          width: 100,
          height: 100,
          backgroundColor: 'green',
        }}
      />
      <Button
        title="Detail"
        onPress={() => props.navigation.navigate('Detail')}
      />
    </SafeAreaView>
  );
};

const Detail = () => {
  return (
    <SafeAreaView>
      <Animated.View
        sharedTransitionTag="sharedTag"
        sharedTransitionStyle={sharedElementTransition}
        style={{
          width: 50,
          height: 50,
          backgroundColor: 'green',
        }}
      />
      <Text>Detail</Text>
    </SafeAreaView>
  );
};

export const App: React.FC<Props> = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator
        screenOptions={{
          headerShown: false,
        }}>
        <Stack.Screen name="Home" component={Home} />
        <Stack.Screen name="Detail" component={Detail} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

Steps to reproduce

  1. Create new RN project
  2. Add React Navigation and Reanimated
  3. Setup a shared transition
  4. Test on an Android emulator

Snack or a link to a repository

https://github.com/nextriot/reanimated-shared-transition-android-bug

Reanimated version

3.0.2

React Native version

0.71.4

Platforms

Android

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

Android emulator

Device model

Galaxy Nexus

Acknowledgements

Yes

prince-sugarfit commented 1 year ago

Facing same issue. In fact, on android every element transitions to start of the screen(x: 0, y: 0). Works fine on iOS.

samuelbeaulieu commented 11 months ago

I'm also facing the same issue, and it's affecting iOS too.

Sudhanshu-Tiwari commented 10 months ago

Facing the same issue but unrelated to status bar. The view randomly changes position before and after the transition.

paulovictor237 commented 9 months ago

“I am going through the same problem version: 3.6.1

piaskowyk commented 9 months ago

Hey 👋 Thank you for the report! Shared Element Transition is still an experimental feature, but we currently working on fixing SET's issues.

ChronoByteCosmonaut commented 9 months ago

What might help is to avoid using SafeAreaView and instead set top padding or whatever you need offset by using the useSafeAreaInsets() hook.