I am developing a React Native application which uses React Navigation to manage the routing between screens.
I know reading React Navigation documentation and watching this video on Egghead.io (highly suggested) that is possible to define custom animations for transitions between screens passing the transitionConfig property to a StackNavigator. 
For example, the following code is defining a slide from left animation that is basically the mirror of the iOS default push animation:
const TransitionConfig = () => ({
    screenInterpolator: ({ layout, position, scene }) => {
        const { index } = scene
        const { initWidth } = layout
        const translateX = position.interpolate({
            inputRange: [index - 1, index, index + 1],
            outputRange: [-initWidth, 0, 0],
        })
        return {
            transform: [{ translateX }],
        }
    }
})
const MyNavigator = createStackNavigator(
    {
        A: {screen: ScreenA},
        B: {screen: ScreenB},
    },
    { transitionConfig: TransitionConfig }
)
Considering the code above and the fact we are navigating from screen A to screen B, the screenInterpolator function body is basically describing the animation the screen B should follow when it's going to appear (it's reverted when it disappears). In this case the code it's saying to translate the screen B along the X axis to achieve a slide in effect. 
Is it possible to also define the animation for the screen that is disappearing (screen A in our case)? I would like to define something like this:
B should appear sliding from left to rightA should disappear sliding from top to bottomI found the answer by myself, I hope will help someone in the future.
I was wrong assuming that screenInterpolator is describing only the behaviour of the screen B, because is actually describing the animation of both A and B. Or better, it's the interpolate function with inputRange and outputRange that allows you to describe the animation for both the entering (B) and leaving (A) screen.
Let's have a closer look to this snippet, keeping in mind that the interpolate function is just creating a 1-1 association between the values of inputRange and outputRange (deeper explanation here). 
const { index } = scene
const translateX = position.interpolate({
    inputRange:  [index - 1, index, index + 1],
    outputRange: [-initWidth, 0, 0],
})
Assumptions:
B and A are screensA to B
width(B) = width(A) = 320width(deviceScreen) = 320initWidth = 320Explanation
index-1 represents the screen that is going to appear (screen B) and it's mapped to -initWidth. With this we are saying that the screen it's going to appear (screen B) should be X-translated (respect the viewport) of a value equal its width. So it will start the animation from X = 320 (i.e. outside the screen)index represents the screen that is going to appear, but once is appeared (still screen B). Mapping it to 0 we are saying that screen B once is appeared should be in position X = 0
index + 1 represents the screen once is going to disappear. This is what it led me to the error. At the beginning I thought this was still and only the screen B, but just when it would have disappeared because of a navigation like  B->C. However from our A->B point of view, it's the screen A the one that is going to disappear! So both line of thoughts are correct, it's all about seeing things from a different perspective. So, mapping index+1 to 0 we are saying that screen A should stay at X=0 when it's going to disappear (i.e. when B is going to appear)Result
This is the animation realized by the code above. As you can see, the screen A remains where it is because of the association index+1 <-> 0 (no translation, so no animation for screen A).

If we change the association of index+1 to index+1 <-> -initWidth, then screen A will also be translated and hence animated :)
const translateX = position.interpolate({
  inputRange:  [index - 1, index, index + 1],
  outputRange: [initWidth, 0, -initWidth],
})

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With