Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Android): restore default Android animations #2110

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

tboba
Copy link
Member

@tboba tboba commented Apr 24, 2024

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

  • Restored system animations by using setTransition on FragmentTransaction
  • Added onCreateAnimator in ScreenStackFragment

Screenshots / 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

  • Ensured that CI passes

@efstathiosntonas
Copy link

efstathiosntonas commented Apr 26, 2024

pasting the patch here just in case someone wants to check fast without installing this PR:

react-native-screens+3.31.1.patch

Click me
diff --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>

@tboba
Copy link
Member Author

tboba commented Apr 26, 2024

Hi @efstathiosntonas, thanks for passing this! Have you checked locally if this change works for you? What do you think about it?

Nevermind, I saw your comment in the issue 馃槃 Great to hear this works correctly!

@tboba
Copy link
Member Author

tboba commented Apr 26, 2024

@efstathiosntonas One more question, have you tried listening to screen lifecycle events (transitionStart/transitionEnd with changing the closing parameter)? I can observe they should work in correct order, but maybe you have different feeling about them? It's a key point for us to keep the order the same as previous animations, since otherwise this could be a breaking change 馃憖

@efstathiosntonas
Copy link

efstathiosntonas commented Apr 26, 2024

@tboba tested it also on S22 A14 and Redmi Note 8 A13 and works fine, feels way better.

ps. yarn prepare inside the node_modules/react-native-screens is gonna be a pain 馃槄

@efstathiosntonas One more question, have you tried listening to screen lifecycle events (transitionStart/transitionEnd with changing the closing parameter)? I can observe they should work in correct order, but maybe you have different feeling about them? It's a key point for us to keep the order the same as previous animations, since otherwise this could be a breaking change 馃憖

never tried this, can you give or point me to a minimal example?

@tboba
Copy link
Member Author

tboba commented Apr 26, 2024

@efstathiosntonas Yeah! On every screen, you can define listeners prop that will serve as an object of your desired listeners. We've got two interesting events there: transitionStart and transitionEnd (each of them have closing prop inside the data, which defines whether screen disappears (true) or appears (false).

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,
                );
              },
            }}
          />

@arasrezaei
Copy link

when available ? 馃憖

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants