StackNavigator: Allow configurable, different transition animations between screens
lintonye opened this issue ยท 9 comments
Motivation
Right now only one kind of animation is supported in a StackNavigator. It's useful to support different transitions between different screens in a same stack. For example, you may want shared elements transition between a photo grid and the photo's detail screen, and the default system transition when navigating to the settings screen.
Proposed API
const SimpleStack = StackNavigator({
PhotoGrid: {
screen: PhotoGrid,
},
PhotoDetail: {
screen: PhotoDetail,
},
Settings: {
screen: Settings,
},
}, {
transitions: [
{routeNames: ['PhotoGrid', 'PhotoDetail'], transition: SharedElements},
// The rest are default: CardStack
]
});Or, better yet, determine the transition dynamically:
{
transition: (fromRoute, toRoute) => {
const routeNames = [ fromRoute.routeName, toRoute.routeName];
return (routeNames.includes('PhotoGrid') && routeNames.includes('PhotoDetail')
? SharedElements
: CardStack);
}
}Implementation Plan
With a minor change to CardStack, which exposes transitionProps and prevTransitionProps to the transitionConfig prop function, we can implement this for simple transitions such as opacity or translateX/Y animations. @ericvicenti also mentioned an approach to allow each screen to define what Card component to use. This should give more flexibility on how individual screens are animated during the transition.
However, for more complex transitions that require information from multiple screens, such as the shared elements transition, we'd need some extra support. See #175.
Sounds interesting. Haven't read it yet, but I think it'll be nicer to specify transition in navigationOptions,
navigationOptions = {
cardStack: {
transition: (fromRoute, toRoute) => {}
},
}@satya164 Thanks. I understand the intention to specify transition in navigationOptions. However, if we do it on a per-screen basis, it seems very easy to introduce configuration conflicts. For example:
ScreenA.navigationOptions = {
cardStack: {
transition: (fromRoute, toRoute) => TransitionA,
}
}
ScreenB.navigationOptions = {
cardStack: {
transition: (fromRoute, toRoute) => TransitionB,
}
}What transition we should use when moving from ScreenA to ScreenB?
In the example you gave, if it's transitioning to B, then the transition property specified in B should be used. Basically navigationOptions.transition is the transition configuration for current screen.
I guess we can simplify it further,
navigationOptions = {
cardStack: {
transition: (previousRoute: Route) => {
// configure the animation here
}
},
}So that it always configures the transition when you're transitioning to the route. In that case, it's not possible to introduce conflicts I think.
when will this configuration be done? I am waiting for this implementation.
Thanks
Any update ?
It's still at the proof-of-concept stage -- far from complete. But feel free to keep track of #175 where I'll send updates from time to time.
I'm not sure what the difference is between this and #175, so I'm gonna close this and let discussion continue there