Android native transition between screens
ferrannp opened this issue · 3 comments
Update 1
This might be even more complicated checking the actual newest source:
activity_open_enter.xml
activity_open_exit.xml
activity_close_enter.xml
activity_close_exit.xml
Original
We had a discussion about this in the past @ericvicenti @satya164. To me, right now it looks similar to the default Android behaviour but still I think it is not as it is on Android. Specially when going back (exit animation).
This is the current implementation (TransitionConfig.js):
// Standard Android navigation transition when opening an Activity
const FadeInFromBottomAndroid = ({
// See http://androidxref.com/7.1.1_r6/xref/frameworks/base/core/res/res/anim/activity_open_enter.xml
transitionSpec: {
duration: 350,
easing: Easing.out(Easing.poly(5)), // decelerate
timing: Animated.timing,
},
screenInterpolator: CardStackStyleInterpolator.forFadeFromBottomAndroid,
} : TransitionConfig);
// Standard Android navigation transition when closing an Activity
const FadeOutToBottomAndroid = ({
// See http://androidxref.com/7.1.1_r6/xref/frameworks/base/core/res/res/anim/activity_close_exit.xml
transitionSpec: {
duration: 230,
easing: Easing.in(Easing.poly(4)), // accelerate
timing: Animated.timing,
},
screenInterpolator: CardStackStyleInterpolator.forFadeFromBottomAndroid,
} : TransitionConfig);But when I check those links: http://androidxref.com/7.1.1_r6/xref/frameworks/base/core/res/res/anim/activity_open_enter.xml & http://androidxref.com/7.1.1_r6/xref/frameworks/base/core/res/res/anim/activity_close_exit.xml#26, I see a different configuration.
in
alpha: 200ms, decelerate_quart(2)
position: 350ms, decelerate_quint(2.5)out
alpha: 150ms, linear, delay 150
position: 250ms, accelerate_quart(2.5)
First of all there are two animations (alpha and position) that run in parallel (with different durations and easing). I've been trying to replicate the values directly in Transitioner.js. Right now it looks like:
const animations = indexHasChanged
? [
timing(
progress,
{
...transitionSpec,
toValue: 1,
},
),
timing(
position,
{
...transitionSpec,
toValue: nextProps.navigation.state.index,
},
),
]
: [];
...
Animated.parallel(animations).start(this._onTransitionEnd);
});I tried to replicate the config:
let alphaDelay = 0, alphaDuration, alphaEasing, positionDuration, positionEasing;
if (transitionSpec.duration === 350) {
alphaDuration = 200;
alphaEasing = Easing.bezier(0.165, 0.840, 0.440, 1.000); // ease-out-quart
positionDuration = 350;
positionEasing = Easing.bezier(0.230, 1.000, 0.320, 1.000); // ease-out-quint
} else { // 250
alphaDuration = 150;
alphaDelay = 100;
alphaEasing = Easing.linear();
positionDuration = 250;
positionEasing = Easing.bezier(0.895, 0.030, 0.685, 0.220); // ease-in-quart
}
const animations = indexHasChanged
? [
timing(
progress,
{
...transitionSpec,
duration: alphaDuration,
easing: alphaEasing,
delay: alphaDelay > 0 ? alphaDelay : 0,
toValue: 1,
},
),
timing(
position,
{
...transitionSpec,
duration: positionDuration,
easing: positionEasing,
toValue: nextProps.navigation.state.index,
},
),
]
: [];
...
Animated.parallel(animations).start(this._onTransitionEnd);It looks like:
But I feel I am still missing something. Even that it uses Animated.parallel, it does not seem that the alpha one (the first one) is affecting at all. Actually, if I remove it completely from the array, I do not see any difference (I think). UPDATE: Instead of parallel I think we need Animated.stagger instead
What do you think? :)
Consider sending a PR that improves animations!
There is also an Android "More" transition when in settings. I created an RFC - react-navigation/rfcs#35
