-
-
Notifications
You must be signed in to change notification settings - Fork 521
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(Android): restore default Android animations #2110
base: main
Are you sure you want to change the base?
Conversation
pasting the patch here just in case someone wants to check fast without installing this PR:
Click mediff --git a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/Screen.kt b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/Screen.kt
index b31e378..acfe9ad 100644
--- a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/Screen.kt
+++ b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/Screen.kt
@@ -278,4 +278,9 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
enum class WindowTraits {
ORIENTATION, COLOR, STYLE, TRANSLUCENT, HIDDEN, ANIMATED, NAVIGATION_BAR_COLOR, NAVIGATION_BAR_HIDDEN
}
+ companion object {
+ fun isSystemAnimation(stackAnimation: StackAnimation): Boolean {
+ return stackAnimation === StackAnimation.DEFAULT || stackAnimation === StackAnimation.FADE || stackAnimation === StackAnimation.NONE
+ }
+ }
}
diff --git a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt
index 3915dd6..2fc1ac4 100644
--- a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt
+++ b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt
@@ -272,7 +272,7 @@ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
// onViewAnimationStart/End is triggered from View#onAnimationStart/End method of the fragment's root
// view. We override an appropriate method of the StackFragment's
// root view in order to achieve this.
- if (isResumed) {
+ if (isResumed || screen.container?.topScreen === screen) {
// Android dispatches the animation start event for the fragment that is being added first
// however we want the one being dismissed first to match iOS. It also makes more sense from
// a navigation point of view to have the disappear event first.
diff --git a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
index 458465c..e12136e 100644
--- a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
+++ b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
@@ -4,6 +4,7 @@ import android.content.Context
import android.graphics.Canvas
import android.os.Build
import android.view.View
+import androidx.fragment.app.FragmentTransaction
import com.facebook.react.bridge.ReactContext
import com.facebook.react.uimanager.UIManagerHelper
import com.swmansion.rnscreens.Screen.StackAnimation
@@ -139,9 +140,9 @@ class ScreenStack(context: Context?) : ScreenContainer(context) {
if (stackAnimation != null) {
if (shouldUseOpenAnimation) {
when (stackAnimation) {
- StackAnimation.DEFAULT -> it.setCustomAnimations(R.anim.rns_default_enter_in, R.anim.rns_default_enter_out)
- StackAnimation.NONE -> it.setCustomAnimations(R.anim.rns_no_animation_20, R.anim.rns_no_animation_20)
- StackAnimation.FADE -> it.setCustomAnimations(R.anim.rns_fade_in, R.anim.rns_fade_out)
+ StackAnimation.DEFAULT -> it.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
+ StackAnimation.NONE -> it.setTransition(FragmentTransaction.TRANSIT_NONE)
+ StackAnimation.FADE -> it.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
StackAnimation.SLIDE_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left)
StackAnimation.SLIDE_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right)
StackAnimation.SLIDE_FROM_BOTTOM -> it.setCustomAnimations(
@@ -152,9 +153,9 @@ class ScreenStack(context: Context?) : ScreenContainer(context) {
}
} else {
when (stackAnimation) {
- StackAnimation.DEFAULT -> it.setCustomAnimations(R.anim.rns_default_exit_in, R.anim.rns_default_exit_out)
- StackAnimation.NONE -> it.setCustomAnimations(R.anim.rns_no_animation_20, R.anim.rns_no_animation_20)
- StackAnimation.FADE -> it.setCustomAnimations(R.anim.rns_fade_in, R.anim.rns_fade_out)
+ StackAnimation.DEFAULT -> it.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE)
+ StackAnimation.NONE -> it.setTransition(FragmentTransaction.TRANSIT_NONE)
+ StackAnimation.FADE -> it.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
StackAnimation.SLIDE_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right)
StackAnimation.SLIDE_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left)
StackAnimation.SLIDE_FROM_BOTTOM -> it.setCustomAnimations(
diff --git a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
index 48ff684..cdf2896 100644
--- a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
+++ b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
@@ -1,5 +1,9 @@
package com.swmansion.rnscreens
+import android.animation.Animator
+import android.animation.AnimatorInflater
+import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
@@ -16,6 +20,9 @@ import android.view.animation.Transformation
import android.widget.LinearLayout
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.fragment.R
+import androidx.fragment.app.FragmentTransaction
+import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.uimanager.PixelUtil
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.AppBarLayout.ScrollingViewBehavior
@@ -86,6 +93,53 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
notifyViewAppearTransitionEnd()
}
+ // Similarly to ScreensCoordinatorLayout, this method listens only for the phases of default Android
+ // transitions (default/none/fade), since `ScreensCoordinatorLayout#startAnimation` is being
+ // called only for custom animations.
+ override fun onCreateAnimator(transit: Int, enter: Boolean, nextAnim: Int): Animator? {
+ val listener = object : AnimatorListenerAdapter() {
+ override fun onAnimationStart(animation: Animator) {
+ onViewAnimationStart()
+ super.onAnimationStart(animation)
+ }
+
+ override fun onAnimationEnd(animation: Animator) {
+ onViewAnimationEnd()
+ super.onAnimationEnd(animation)
+ }
+ }
+
+ // If there's custom animation set, use default onCreateAnimator implementation, as event
+ // handling will be handled by ScreensCoordinatorLayout.
+ if (!Screen.isSystemAnimation(screen.stackAnimation)) {
+ return super.onCreateAnimator(transit, enter, nextAnim)
+ }
+
+ // When fragment is being removed or there's no transition selected, we simply
+ // return AnimatorSet without any animation.
+ if (isRemoving || transit == FragmentTransaction.TRANSIT_NONE) {
+ return AnimatorSet().apply {
+ addListener(listener)
+ }
+ }
+
+ var selectedNextAnim = nextAnim
+ if (nextAnim == 0) {
+ selectedNextAnim = when (transit) {
+ FragmentTransaction.TRANSIT_FRAGMENT_OPEN -> if (enter) R.animator.fragment_open_enter else R.animator.fragment_open_exit
+ FragmentTransaction.TRANSIT_FRAGMENT_CLOSE -> if (enter) R.animator.fragment_close_enter else R.animator.fragment_close_exit
+ FragmentTransaction.TRANSIT_FRAGMENT_FADE -> if (enter) R.animator.fragment_fade_enter else R.animator.fragment_fade_exit
+ else -> 0
+ }
+ }
+
+ val animator = AnimatorInflater.loadAnimator(context, selectedNextAnim).apply {
+ addListener(listener)
+ }
+
+ return animator
+ }
+
private fun notifyViewAppearTransitionEnd() {
val screenStack = view?.parent
if (screenStack is ScreenStack) {
diff --git a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_enter_in.xml b/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_enter_in.xml
deleted file mode 100644
index 4398c7e..0000000
--- a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_enter_in.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android">
- <alpha
- android:interpolator="@android:interpolator/accelerate_decelerate"
- android:fromAlpha="0"
- android:toAlpha="1.0"
- android:startOffset="100"
- android:duration="100"/>
- <scale
- android:interpolator="@android:interpolator/accelerate_decelerate"
- android:fromXScale="0.85"
- android:toXScale="1"
- android:fromYScale="0.85"
- android:toYScale="1"
- android:pivotX="50%"
- android:pivotY="50%"
- android:duration="200"/>
-</set>
diff --git a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_enter_out.xml b/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_enter_out.xml
deleted file mode 100644
index 84c9175..0000000
--- a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_enter_out.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android">
- <alpha
- android:fromAlpha="1"
- android:toAlpha="0.4"
- android:startOffset="100"
- android:duration="100"
- android:interpolator="@android:interpolator/accelerate_decelerate" />
-
- <scale
- android:interpolator="@android:interpolator/accelerate_decelerate"
- android:fromXScale="1"
- android:toXScale="1.15"
- android:fromYScale="1"
- android:toYScale="1.15"
- android:pivotX="50%"
- android:pivotY="50%"
- android:duration="200"/>
-</set>
diff --git a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_exit_in.xml b/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_exit_in.xml
deleted file mode 100644
index 6d6fa02..0000000
--- a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_exit_in.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false">
- <alpha
- android:fromAlpha="0.0"
- android:toAlpha="1"
- android:startOffset="50"
- android:duration="100"/>
- <scale
- android:fromXScale="1.15"
- android:toXScale="1"
- android:fromYScale="1.15"
- android:toYScale="1"
- android:pivotX="50%"
- android:pivotY="50%"
- android:duration="200"/>
-</set>
diff --git a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_exit_out.xml b/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_exit_out.xml
deleted file mode 100644
index b20a184..0000000
--- a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_default_exit_out.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false"
- android:zAdjustment="top">
- <alpha
- android:fromAlpha="1"
- android:toAlpha="0.0"
- android:startOffset="50"
- android:duration="100"/>
- <scale
- android:fromXScale="1"
- android:toXScale="0.85"
- android:fromYScale="1"
- android:toYScale="0.85"
- android:pivotX="50%"
- android:pivotY="50%"
- android:duration="200"/>
-</set>
diff --git a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_fade_in.xml b/node_modules/react-native-screens/android/src/main/res/base/anim/rns_fade_in.xml
deleted file mode 100644
index c78ea61..0000000
--- a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_fade_in.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--Duration taken from debugging source code-->
-<alpha xmlns:android="http://schemas.android.com/apk/res/android"
- android:fromAlpha="0.0"
- android:toAlpha="1.0"
- android:duration="150"
- /> <!--Remember to change duration in the corresponding xml when modifying it-->
diff --git a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_fade_to_bottom.xml b/node_modules/react-native-screens/android/src/main/res/base/anim/rns_fade_to_bottom.xml
index 2334521..3b7e7a1 100644
--- a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_fade_to_bottom.xml
+++ b/node_modules/react-native-screens/android/src/main/res/base/anim/rns_fade_to_bottom.xml
@@ -2,14 +2,14 @@
<!--Android Nougat exit animation-->
<!--http://aosp.opersys.com/xref/android-7.1.2_r37/xref/frameworks/base/core/res/res/anim/activity_close_exit.xml-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false">
+ android:shareInterpolator="false">
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
- android:interpolator="@android:interpolator/linear"
- android:startOffset="100"
- android:duration="150"/>
+ android:interpolator="@android:interpolator/linear"
+ android:startOffset="100"
+ android:duration="150"/>
<translate android:fromYDelta="0%" android:toYDelta="8%"
- android:interpolator="@android:interpolator/accelerate_quint"
- android:duration="250"/> <!--we use rns_no_animation_250.xml as the other animation for
+ android:interpolator="@android:interpolator/accelerate_quint"
+ android:duration="250"/> <!--we use rns_no_animation_250.xml as the other animation for
this transition since we want both of them to end at the same time. Remember to change
duration in both files when modifying it-->
</set>
diff --git a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_no_animation_20.xml b/node_modules/react-native-screens/android/src/main/res/base/anim/rns_no_animation_20.xml
deleted file mode 100644
index 5cc0d23..0000000
--- a/node_modules/react-native-screens/android/src/main/res/base/anim/rns_no_animation_20.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<alpha xmlns:android="http://schemas.android.com/apk/res/android"
- android:fromAlpha="1.0"
- android:toAlpha="1.0"
- android:duration="20"
- /> <!-- non-zero duration ensures transition events are triggered correctly -->
diff --git a/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_enter_in.xml b/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_enter_in.xml
deleted file mode 100644
index 1767203..0000000
--- a/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_enter_in.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false">
-
- <alpha
- android:fromAlpha="0.0"
- android:toAlpha="1.0"
- android:fillEnabled="true"
- android:fillBefore="true"
- android:fillAfter="true"
- android:interpolator="@android:anim/linear_interpolator"
- android:startOffset="50"
- android:duration="83" />
-
- <translate
- android:fromXDelta="10%"
- android:toXDelta="0"
- android:fillEnabled="true"
- android:fillBefore="true"
- android:fillAfter="true"
- android:interpolator="@android:interpolator/fast_out_extra_slow_in"
- android:duration="450" />
-
- <extend
- android:fromExtendLeft="10%"
- android:fromExtendTop="0"
- android:fromExtendRight="0"
- android:fromExtendBottom="0"
- android:toExtendLeft="10%"
- android:toExtendTop="0"
- android:toExtendRight="0"
- android:toExtendBottom="0"
- android:interpolator="@android:interpolator/fast_out_extra_slow_in"
- android:startOffset="0"
- android:duration="450" />
-</set>
diff --git a/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_enter_out.xml b/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_enter_out.xml
deleted file mode 100644
index e7dd72b..0000000
--- a/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_enter_out.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false">
-
- <alpha
- android:fromAlpha="1.0"
- android:toAlpha="1.0"
- android:fillEnabled="true"
- android:fillBefore="true"
- android:fillAfter="true"
- android:interpolator="@anim/rns_standard_accelerate_interpolator"
- android:startOffset="0"
- android:duration="450" />
-
- <translate
- android:fromXDelta="0"
- android:toXDelta="-10%"
- android:fillEnabled="true"
- android:fillBefore="true"
- android:fillAfter="true"
- android:interpolator="@android:interpolator/fast_out_extra_slow_in"
- android:startOffset="0"
- android:duration="450" />
-
- <extend
- android:fromExtendLeft="0"
- android:fromExtendTop="0"
- android:fromExtendRight="10%"
- android:fromExtendBottom="0"
- android:toExtendLeft="0"
- android:toExtendTop="0"
- android:toExtendRight="10%"
- android:toExtendBottom="0"
- android:interpolator="@android:interpolator/fast_out_extra_slow_in"
- android:startOffset="0"
- android:duration="450" />
-</set>
diff --git a/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_exit_in.xml b/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_exit_in.xml
deleted file mode 100644
index 949ebb7..0000000
--- a/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_exit_in.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false">
-
- <alpha
- android:fromAlpha="1.0"
- android:toAlpha="1.0"
- android:fillEnabled="true"
- android:fillBefore="true"
- android:fillAfter="true"
- android:interpolator="@android:interpolator/linear"
- android:startOffset="0"
- android:duration="450" />
-
- <translate
- android:fromXDelta="-10%"
- android:toXDelta="0"
- android:fillEnabled="true"
- android:fillBefore="true"
- android:fillAfter="true"
- android:interpolator="@android:interpolator/fast_out_extra_slow_in"
- android:startOffset="0"
- android:duration="450" />
-
- <extend
- android:fromExtendLeft="0"
- android:fromExtendTop="0"
- android:fromExtendRight="10%"
- android:fromExtendBottom="0"
- android:toExtendLeft="0"
- android:toExtendTop="0"
- android:toExtendRight="10%"
- android:toExtendBottom="0"
- android:interpolator="@android:interpolator/fast_out_extra_slow_in"
- android:startOffset="0"
- android:duration="450" />
-</set>
diff --git a/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_exit_out.xml b/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_exit_out.xml
deleted file mode 100644
index ba4d84d..0000000
--- a/node_modules/react-native-screens/android/src/main/res/v33/anim-v33/rns_default_exit_out.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false">
-
- <alpha
- android:fromAlpha="1.0"
- android:toAlpha="0.0"
- android:fillEnabled="true"
- android:fillBefore="true"
- android:fillAfter="true"
- android:interpolator="@android:interpolator/linear"
- android:startOffset="35"
- android:duration="83" />
-
- <translate
- android:fromXDelta="0"
- android:toXDelta="10%"
- android:fillEnabled="true"
- android:fillBefore="true"
- android:fillAfter="true"
- android:interpolator="@android:interpolator/fast_out_extra_slow_in"
- android:startOffset="0"
- android:duration="450" />
-
- <extend
- android:fromExtendLeft="10%"
- android:fromExtendTop="0"
- android:fromExtendRight="0"
- android:fromExtendBottom="0"
- android:toExtendLeft="10%"
- android:toExtendTop="0"
- android:toExtendRight="0"
- android:toExtendBottom="0"
- android:interpolator="@android:interpolator/fast_out_extra_slow_in"
- android:startOffset="0"
- android:duration="450" />
-</set> |
Nevermind, I saw your comment in the issue 😄 Great to hear this works correctly! |
@efstathiosntonas One more question, have you tried listening to screen lifecycle events (transitionStart/transitionEnd with changing the |
@tboba tested it also on S22 A14 and Redmi Note 8 A13 and works fine, feels way better. ps.
never tried this, can you give or point me to a minimal example? |
@efstathiosntonas Yeah! On every screen, you can define For example, you can define listeners inside the stack definition like this: <Stack.Screen
name="First"
component={First}
listeners={{
transitionStart: ({ data }) => {
console.log(
`screen A: transition start (closing: ${data.closing})`,
data,
);
},
transitionEnd: ({ data }) => {
console.log(
`screen A: transition end (closing: ${data.closing}`,
data,
);
},
}}
/>
<Stack.Screen
name="Second"
component={Second}
listeners={{
transitionStart: ({ data }) => {
console.log(
`screen B: transition start (closing: ${data.closing})`,
data,
);
},
transitionEnd: ({ data }) => {
console.log(
`screen B: transition end (closing: ${data.closing}`,
data,
);
},
}}
/> |
when available ? 👀 |
@arasrezaei Hey! This PR is currently blocked with the issue about the wrong order of disappearing screens from the native-stack. Previously, while the next screen was sending |
i wish i could help :)) |
stack screen transition is not by default native WhatsApp.Video.June.13.1.mp4and this other app is currently I'm building with expo 51 and react native 0.74 with react-native-screen @3.31.1 WhatsApp.Video.June.13.mp4you can clearly see that second one is not default native at all and kind of feels a little bit laggy compared to how it was in react native screens @~3.29.0 before this pr #2019 |
@dhruv-00 twitter app definitely has custom transitions. It doesn't look like Android 14 default transitions. If you want to see how native transitions look like, then you can open Settings app and check there - and these transactions look very close to transitions from your second video. |
I've checked settings app and it is nothing close to as second video it is the same as the first video |
This is how it looks on my Pixel 7 Pro with stock firmware: screen-20240621-235315.mp4 |
Record_2024-06-22-02-35-38.mp4This is how it looks in my OnePlus 12 settings |
@dhruvpvx I think Oppo/Xiaomi/Samsung and many other companies are creating their own version of UI (MIUI/One UI etc.) and it is varying significantly. And transitions that you see most likely are also a modification (i. e. it's not default Android transitions). If you want to check original Android transitions - you may check transitions in emulator for specific version. From what I know - it's impossible to get transitions specific to a particular fork of Android, because typically transitions are overriden on app level (and not on OS level). I. e. Settings app on OnePlus device just uses their own transitions and these transitions are private and can not be retrieved on OS level. @tboba correct me if I'm wrong please 😅 |
@kirillzyusko Yeah, that's correct - from what I can see is that Samsung/OPPO/any other distros are oftenly overriding the transitions to the custom one. I think the best source to check the original Android Transition is the official Material documentation - for example, take a look on However, I know that Material 3 also introduces their own animations, which we may try to introduce yet in this PR (Applying Easing and Duration). Still, the main blocker is the way how we can't overlap entering and existing animations in current implementation. |
please, we need this PR (●'◡'●) |
I am so waiting for this, are there any plans ? |
Hey hey @arasrezaei, unfortunately this PR is blocked by the wrong order of incoming events related to screen mounting/unmounting, which leads to the breaking change we definitely don't want by merging this. Also, if you look frame by frame how screens are being mounted, you can see that transition doesn't overlay from one screen to another (and so far I can't find any solutions how this could be fixed). If you want this change really badly - go ahead and patch-package |
Description
TL;DR: Default Android animations are finally there! \o/
Currently, in React Native Screens we're using XML-based Android custom animations, even for the default transitions, provided by system. The main reason behind it was the fact, that during the times when this PR was introduced, events related to the screen lifecycle (will appear, appear, will disappear, disappear) were really unstable and it was painful to ensure that
onAppear
won't be called twice.This PR restores default Android transitions for animations:
default
,none
,fade
and fixes earlier problems, related to the lifecycle by dispatching those events in Animator.Fixes #2100, fixes #1968 and should invalidate all of the previous issues: #1223 #1640 #1879.
Changes
setTransition
on FragmentTransactiononCreateAnimator
in ScreenStackFragmentScreenshots / GIFs
Will add later 😁
Before
After
Test code and steps to reproduce
You can use
Test1072.tsx
to check how the animations look like.Checklist