Shared Element Transition (Android)

Android supports shared element transitions, where you can smoothly animate between UI elements that are common across two scenes. The Navigation router exposes this functionality to React using the SharedElementAndroid component. To identify a pair of shareable elements, you wrap each one in a SharedElementAndroid component and give them both the same name.

In our email example app, we can smooth out the transition when a user opens an email by sharing the subject of the email between the 'inbox' scene and the 'mail' scene. We wrap the subject elements on each scene inside a SharedElementAndroid component and give them both the same name.

// The 'inbox' scene
<TouchableHighlight
    onPress={() => {
        stateNavigator.navigate('mail', {id: id});
    }}>
    <SharedElementAndroid name={'email' + id}>
        <Text>Meeting invite</Text>
    </SharedElementAndroid>
</TouchableHighlight>
// The 'mail' scene
<SharedElementAndroid name={'email' + id}>
    <Text>Meeting invite</Text>
</SharedElementAndroid>

When you navigate between two States, the Navigation router calls the function you assign to the sharedElements prop of the NavigationStack component. You return an array containing the names of the shared elements that are to participate in the transition. In our email example, we check the destination is the 'mail' State before returning the name corresponding to the selected email.

<NavigationHandler stateNavigator={stateNavigator}>
  <NavigationStack sharedElements={(state, data) => (
    state.key === 'mail' ? ['email' + data.id] : null
  )} />
</NavigationHandler>                

Customising Transitions

You can change the default shared element animation by creating an Android transition resource file. In our email example application, we want the email subject to overshoot its target slightly before settling into place. Inside Android Studio, we right click the root of our project and choose 'New -> Android Resource File'. In the pop-up dialog, we enter a name of 'email_overshoot', pick 'Transition' from the resource type dropdown and enter 'transition' for the directory name. We configure our animation using the built-in 'overshoot' interpolator.

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeBounds android:interpolator="@android:interpolator/overshoot"/>
</transitionSet>

To get this animation to play when the 'mail' scene's Text component mounts and unmounts, we pass the name of our resource file to the transition prop of the SharedElementAndroid component.

// The 'mail' scene
<SharedElementAndroid name={'email' + id} transition="email_overshoot">
    <Text>Meeting invite</Text>
</SharedElementAndroid>