diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt index 75453fa7ae..f7ade4af60 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt @@ -3,12 +3,23 @@ package com.swmansion.rnscreens import android.content.Context import android.graphics.Canvas import android.os.Build +import android.util.Log import android.view.View +import androidx.core.view.children +import androidx.transition.Fade +import androidx.transition.Slide +import androidx.transition.Transition +import androidx.transition.TransitionManager +import androidx.transition.TransitionSet +import androidx.transition.Visibility +import com.facebook.fresco.ui.common.DimensionsInfo import com.facebook.react.bridge.ReactContext import com.facebook.react.uimanager.UIManagerHelper import com.swmansion.rnscreens.Screen.StackAnimation import com.swmansion.rnscreens.bottomsheet.DimmingFragment import com.swmansion.rnscreens.events.StackFinishTransitioningEvent +import com.swmansion.rnscreens.ext.addChildrenToTransition +import com.swmansion.rnscreens.ext.parentAsViewGroup import java.util.Collections import kotlin.collections.ArrayList import kotlin.collections.HashSet @@ -143,9 +154,9 @@ class ScreenStack( stackAnimation = topScreenWrapper?.screen?.stackAnimation } - createTransaction().let { + createTransaction().let { it -> // animation logic start - if (stackAnimation != null) { + if (stackAnimation != null && false) { if (shouldUseOpenAnimation) { when (stackAnimation) { StackAnimation.DEFAULT -> @@ -264,7 +275,78 @@ class ScreenStack( // remove all screens previously on stack for (fragmentWrapper in stack) { if (!screenWrappers.contains(fragmentWrapper) || dismissedWrappers.contains(fragmentWrapper)) { - it.remove(fragmentWrapper.fragment) + if (fragmentWrapper.fragment is DimmingFragment) { + val dimmingFragment = fragmentWrapper.fragment as DimmingFragment + + val fadeOutTransition = Fade(Fade.MODE_OUT).apply { + addTarget(dimmingFragment.containerView) + dimmingFragment.containerView.addChildrenToTransition(this) + excludeChildren(dimmingFragment.dimmingView, true) + duration = 500 + } + + val slideDownTransition = Slide().apply { + addTarget(dimmingFragment.screen) + dimmingFragment.screen.addChildrenToTransition(this) + duration = 500 + } + + dimmingFragment.exitTransition = TransitionSet().apply { + ordering = TransitionSet.ORDERING_TOGETHER + addTransition(fadeOutTransition) + addTransition(slideDownTransition) + } + } else { + val stackFragment = fragmentWrapper.fragment as ScreenStackFragment + val fadeOutTransition = Fade(Fade.OUT).apply { + addTarget(stackFragment.coordinatorLayout) + stackFragment.coordinatorLayout.addChildrenToTransition(this) + duration = 1000 + } + val slideDownTransition = Slide().apply { + addTarget(stackFragment.coordinatorLayout) + stackFragment.coordinatorLayout.addChildrenToTransition(this) + duration = 1000 + } + fragmentWrapper.fragment.exitTransition = TransitionSet().apply { + ordering = TransitionSet.ORDERING_TOGETHER + duration = 1000 + addTransition(fadeOutTransition) + addTransition(slideDownTransition) + addListener(object : Transition.TransitionListener { + var ended = false + + override fun onTransitionStart(transition: Transition) { + Log.i(TAG, "onTransitionStart") + } + + override fun onTransitionEnd(transition: Transition) { + Log.i(TAG, "onTransitionEnd") + if (ended) { + return + } + ended = true + transition.removeListener(this) + createTransaction().remove(fragmentWrapper.fragment) + .commit() + } + + override fun onTransitionCancel(transition: Transition) { + } + + override fun onTransitionPause(transition: Transition) { + } + + override fun onTransitionResume(transition: Transition) = Unit + + }) + } + TransitionManager.beginDelayedTransition(stackFragment.coordinatorLayout.parentAsViewGroup()!!, + stackFragment.exitTransition as TransitionSet? + ) + } +// it.remove(fragmentWrapper.fragment) + return } } for (fragmentWrapper in screenWrappers) { diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt index b11a19f48f..c8c1c7abc2 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt @@ -67,7 +67,7 @@ class ScreenStackFragment : var searchView: CustomSearchView? = null var onSearchViewCreate: ((searchView: CustomSearchView) -> Unit)? = null - private lateinit var coordinatorLayout: ScreensCoordinatorLayout + public lateinit var coordinatorLayout: ScreensCoordinatorLayout private val screenStack: ScreenStack get() { @@ -194,6 +194,7 @@ class ScreenStackFragment : if (screen.stackPresentation != Screen.StackPresentation.FORM_SHEET) { return null } + return null return if (enter) { AnimationUtils.loadAnimation(context, R.anim.rns_slide_in_from_bottom) } else { @@ -565,7 +566,7 @@ class ScreenStackFragment : screenStack.dismiss(this) } - private class ScreensCoordinatorLayout( + class ScreensCoordinatorLayout( context: Context, private val fragment: ScreenStackFragment, // ) : CoordinatorLayout(context), ReactCompoundViewGroup, ReactHitSlopView { diff --git a/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingFragment.kt b/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingFragment.kt index b719be8861..c228085d60 100644 --- a/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingFragment.kt +++ b/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingFragment.kt @@ -51,8 +51,8 @@ class DimmingFragment( Animation.AnimationListener, OnApplyWindowInsetsListener, NativeDismissalObserver { - private lateinit var dimmingView: DimmingView - private lateinit var containerView: GestureTransparentViewGroup + public lateinit var dimmingView: DimmingView + public lateinit var containerView: GestureTransparentViewGroup private val maxAlpha: Float = 0.15F @@ -180,10 +180,14 @@ class DimmingFragment( nextAnim: Int, ): Animation? = // We want dimming view to have always fade animation in current usages. - AnimationUtils.loadAnimation( - context, - if (enter) R.anim.rns_fade_in else R.anim.rns_fade_out, - ) + if (enter) { + AnimationUtils.loadAnimation( + context, + if (enter) R.anim.rns_fade_in else R.anim.rns_fade_out, + ) + } else { + null + } override fun onCreateView( inflater: LayoutInflater, diff --git a/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt b/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt index f48561da18..8b52a06d8a 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +++ b/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt @@ -3,6 +3,8 @@ package com.swmansion.rnscreens.ext import android.graphics.drawable.ColorDrawable import android.view.View import android.view.ViewGroup +import androidx.core.view.children +import androidx.transition.Transition import com.facebook.react.views.scroll.ReactHorizontalScrollView import com.facebook.react.views.scroll.ReactScrollView import com.swmansion.rnscreens.ScreenStack @@ -54,3 +56,12 @@ internal fun View.isInsideScrollViewWithRemoveClippedSubviews(): Boolean { } return false } + +internal fun ViewGroup.addChildrenToTransition(transition: Transition) { + this.children.forEach { + transition.addTarget(it) + if (it is ViewGroup) { + it.addChildrenToTransition(transition) + } + } +}