Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ class ScreenStack(
}

override fun endViewTransition(view: View) {
require(view is ScreensCoordinatorLayout) {
"[RNScreens] Expected children of type: ${ScreensCoordinatorLayout::class.java.simpleName}"
}
if (view.blockFrameworkTransitionFinalization) {
return
}

super.endViewTransition(view)

disappearingTransitioningChildren.remove(view)
Expand All @@ -89,10 +96,17 @@ class ScreenStack(
}
}

fun onViewAppearTransitionEnd() {
internal fun onViewTransitionEnd(view: ScreensCoordinatorLayout) {
if (!removalTransitionStarted) {
dispatchOnFinishTransitioning()
}

if (view.needsTransitionFinalization) {
check(!view.blockFrameworkTransitionFinalization) {
"[RNScreens] Attempt to finalize transition on view that blocks the action!"
}
endViewTransition(view)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,17 @@ class ScreenStackFragment :

override fun onViewAnimationEnd() {
super.onViewAnimationEnd()

// Rely on guards inside the callee to detect whether this was indeed appear transition.
notifyViewAppearTransitionEnd()

// Rely on guards inside the callee to detect whether this was indeed removal transition.
screen.endRemovalTransition()
notifyViewTransitionEnd()
}

private fun notifyViewAppearTransitionEnd() {
private fun notifyViewTransitionEnd() {
val screenStack = view?.parent
if (screenStack is ScreenStack) {
screenStack.onViewAppearTransitionEnd()
screenStack.onViewTransitionEnd(coordinatorLayout)
}

// Rely on guards inside the callee to detect whether this was indeed removal transition.
screen.endRemovalTransition()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,17 @@ class TabsHost(
@Suppress("SENSELESS_COMPARISON") // layoutCallback can be null here since this method can be called in init
if (!isLayoutEnqueued && layoutCallback != null) {
isLayoutEnqueued = true
// we use NATIVE_ANIMATED_MODULE choreographer queue because it allows us to catch the current
// looper loop instead of enqueueing the update in the next loop causing a one frame delay.
ReactChoreographer
.getInstance()
.postFrameCallback(
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
layoutCallback,
)
post {
layoutCallback.doFrame(0)
}
// // we use NATIVE_ANIMATED_MODULE choreographer queue because it allows us to catch the current
// // looper loop instead of enqueueing the update in the next loop causing a one frame delay.
// ReactChoreographer
// .getInstance()
// .postFrameCallback(
// ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
// layoutCallback,
// )
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ internal class ScreensCoordinatorLayout(
PointerEventsBoxNoneImpl(),
)

internal var blockFrameworkTransitionFinalization = false
internal var needsTransitionFinalization = false

override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets = super.onApplyWindowInsets(insets)

private val animationListener: Animation.AnimationListener =
Expand All @@ -32,7 +35,12 @@ internal class ScreensCoordinatorLayout(
}

override fun onAnimationEnd(animation: Animation) {
if (blockFrameworkTransitionFinalization) {
blockFrameworkTransitionFinalization = false
needsTransitionFinalization = true
}
fragment.onViewAnimationEnd()
needsTransitionFinalization = false
}

override fun onAnimationRepeat(animation: Animation) {}
Expand All @@ -50,6 +58,16 @@ internal class ScreensCoordinatorLayout(
// We also add fakeAnimation to the set of animations, which sends the progress of animation
val fakeAnimation = ScreensAnimation(fragment).apply { duration = animation.duration }

if (fragment.isRemoving) {
// This is a hack.
// We'll finalize the transition via our listener.
// We do it to prevent the framework from ending the transition prematurely,
// due to interaction between `FragmentAnim.EndViewTransitionAnimation` and
// `SafeAreaView` drawing blocking logic. For detailed description see:
// TODO LINK THE PR HERE
blockFrameworkTransitionFinalization = true
}

if (animation is AnimationSet && !fragment.isRemoving) {
animation
.apply {
Expand Down
Loading