IjzerenHein / react-native-shared-element

Native shared element transition "primitives" for react-native 💫
MIT License
2.19k stars 94 forks source link

Support ModalPresentationIOS transition preset #23

Open mrousavy opened 4 years ago

mrousavy commented 4 years ago

The animation begins smoothly, but when the animation finishes, the items (SharedElements) are off by some pixels which causes this stuttering glitch. This issue only appears when using the ModalPresentationIOS transition preset. All other presets work fine.

Demo here: Screen-Recording-2020-03-28-at-19 09 06

My Navigator:

const SharedElementStack = createSharedElementStackNavigator();
function HomeSharedElementStackNavigator() {
  return (
    <SharedElementStack.Navigator
      mode="modal"
      screenOptions={{
        gestureEnabled: false,
        cardOverlayEnabled: true,
        ...TransitionPresets.ModalPresentationIOS,     // <-- The preset causing this issue!
      }}
      headerMode="none">
      <SharedElementStack.Screen
        name="HomeGridScreen"
        component={HomeGridScreen}
      />
      <SharedElementStack.Screen
        name="ItemDetailsScreen"
        component={ItemDetailsScreen}
        sharedElementsConfig={(route, otherRoute, showing) => {
          const {item} = route.params;
          return [
            {
              id: `item.${item.id}.image`,
              animation: 'fade',
            },
            {
              id: `item.${item.id}.title`,
              animation: 'fade',
            },
            {
              id: `item.${item.id}.description`,
              animation: 'fade',
            },
          ];
        }}
      />
    </SharedElementStack.Navigator>
  );
}

I've tried playing around with the animation property, but I can't seem to get it working with this animation I found in the example project (springyFadeIn.js):

import {Animated} from 'react-native';
export function springyFadeIn() {
  const transitionSpec = {
    timing: Animated.spring,
    tension: 10,
    useNativeDriver: true,
  };
  return {
    transitionSpec,
    screenInterpolator: ({position, scene}) => {
      const {index} = scene;

      const opacity = position.interpolate({
        inputRange: [index - 1, index],
        outputRange: [0, 1],
      });

      return {opacity};
    },
  };
}

Packages used:

// ...
    "react": "16.9.0",
    "react-native": "0.61.5",
    "react-navigation-shared-element": "^5.0.0-alpha1",
// ...

I don't know if that's a bug in the library or if I am making a mistake, would appreciate some help here!

mrousavy commented 4 years ago

I've investigated the issue further and noticed that this bug only appears when using the ModalPresentationIOS or ScaleFromCenterAndroid transition preset in the screenOptions of the Navigator.

<SharedElementStack.Navigator
  mode="modal"
  screenOptions={{
    gestureEnabled: false,
    cardOverlayEnabled: true,
    ...TransitionPresets.ModalPresentationIOS,      // <-- this right here
  }}
  ...
IjzerenHein commented 4 years ago

Hi 👋This problem appears to be on the native side and is has to do with additional "transforms" applied by the ModalPresentationIOS.

Unfortunately ModalPresentationIOS wont work at the moment.

IjzerenHein commented 4 years ago

I've moved this issue here 👍

AmnaHijjawi commented 3 years ago

+1

evanjmg commented 3 years ago

+1

evanjmg commented 3 years ago

TransitionPresets.ModalSlideFromBottomIOS works better for now as a workaround

IjzerenHein commented 3 years ago

Status update: This preset still doesn't work on both Android and iOS. Some glitches have been resolved with regards to vertical translations, but the top position is still not obtained correctly. As an alternative, please use one of the other presets (nearly all of them work correctly). You can view the supported transitions in the react-navigation example app: https://github.com/IjzerenHein/react-navigation-shared-element/tree/main/example