From 0c310cbfa0d9631a050848565c30f95ce4b529e8 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Fri, 15 Nov 2024 15:39:52 +0100 Subject: [PATCH 01/12] Prevent removal from parent when transitioning --- .../com/facebook/react/views/view/ReactClippingViewManager.kt | 2 +- .../java/com/facebook/react/views/view/ReactViewGroup.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt index da19e945b52a..6f6b2feffe5f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt @@ -65,7 +65,7 @@ public abstract class ReactClippingViewManager : ViewGroupMa if (child.parent != null) { parent.removeView(child) } - parent.removeViewWithSubviewClippingEnabled(child) + parent.removeViewWithSubviewClippingEnabled(child, true) } } else { parent.removeViewAt(index) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 3396c6b3af46..50a393cf4adc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -723,7 +723,7 @@ public void run() { } } - /*package*/ void removeViewWithSubviewClippingEnabled(View view) { + /*package*/ void removeViewWithSubviewClippingEnabled(View view, boolean viewRemovedFromParent) { UiThreadUtil.assertOnUiThread(); Assertions.assertCondition(mRemoveClippedSubviews); @@ -731,7 +731,7 @@ public void run() { Assertions.assertNotNull(mAllChildren); view.removeOnLayoutChangeListener(mChildrenLayoutChangeListener); int index = indexOfChildInAllChildren(view); - if (mAllChildren[index].getParent() != null) { + if (!viewRemovedFromParent && mAllChildren[index].getParent() != null) { int clippedSoFar = 0; for (int i = 0; i < index; i++) { if (mAllChildren[i].getParent() == null) { From ca9a22d19b80937b63d0175eead4e36fb6618b0f Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Sun, 24 Nov 2024 00:45:52 +0100 Subject: [PATCH 02/12] Track children removed while transitioning --- .../views/view/ReactClippingViewManager.kt | 6 ++-- .../react/views/view/ReactViewGroup.java | 35 ++++++++++++++++--- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt index 6f6b2feffe5f..a0ee071205cf 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt @@ -62,14 +62,12 @@ public abstract class ReactClippingViewManager : ViewGroupMa if (removeClippedSubviews) { val child = getChildAt(parent, index) if (child != null) { - if (child.parent != null) { - parent.removeView(child) - } - parent.removeViewWithSubviewClippingEnabled(child, true) + parent.removeViewWithSubviewClippingEnabled(child) } } else { parent.removeViewAt(index) } + } override fun removeAllViews(parent: T) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 50a393cf4adc..673bf4bd02fd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -140,6 +140,9 @@ public void shutdown() { private @Nullable Path mPath; private float mBackfaceOpacity; private String mBackfaceVisibility; + private boolean mIsTransitioning = false; + private @Nullable Set mChildrenRemovedWhileTransitioning = null; + /** * Creates a new `ReactViewGroup` instance. @@ -369,12 +372,14 @@ public void setRemoveClippedSubviews(boolean removeClippedSubviews) { mAllChildren[i] = child; child.addOnLayoutChangeListener(mChildrenLayoutChangeListener); } + mChildrenRemovedWhileTransitioning = new HashSet<>(); updateClippingRect(); } else { // Add all clipped views back, deallocate additional arrays, remove layoutChangeListener Assertions.assertNotNull(mClippingRect); Assertions.assertNotNull(mAllChildren); Assertions.assertNotNull(mChildrenLayoutChangeListener); + Assertions.assertNotNull(mChildrenRemovedWhileTransitioning); for (int i = 0; i < mAllChildrenCount; i++) { mAllChildren[i].removeOnLayoutChangeListener(mChildrenLayoutChangeListener); } @@ -384,6 +389,7 @@ public void setRemoveClippedSubviews(boolean removeClippedSubviews) { mClippingRect = null; mAllChildrenCount = 0; mChildrenLayoutChangeListener = null; + mChildrenRemovedWhileTransitioning = null; } } @@ -410,6 +416,23 @@ public void updateClippingRect() { updateClippingToRect(mClippingRect); } + @Override + public void startViewTransition(View view) { + super.startViewTransition(view); + mIsTransitioning = true; + } + + @Override + public void endViewTransition(View view) { + super.endViewTransition(view); + mIsTransitioning = false; + if (mChildrenRemovedWhileTransitioning != null) { + mChildrenRemovedWhileTransitioning.clear(); + mChildrenRemovedWhileTransitioning = null; + } + } + + private void updateClippingToRect(Rect clippingRect) { Assertions.assertNotNull(mAllChildren); int clippedSoFar = 0; @@ -723,24 +746,28 @@ public void run() { } } - /*package*/ void removeViewWithSubviewClippingEnabled(View view, boolean viewRemovedFromParent) { + /*package*/ void removeViewWithSubviewClippingEnabled(View view) { UiThreadUtil.assertOnUiThread(); - Assertions.assertCondition(mRemoveClippedSubviews); Assertions.assertNotNull(mClippingRect); Assertions.assertNotNull(mAllChildren); + Assertions.assertNotNull(mChildrenRemovedWhileTransitioning); + + handleRemoveView(view); view.removeOnLayoutChangeListener(mChildrenLayoutChangeListener); + int index = indexOfChildInAllChildren(view); - if (!viewRemovedFromParent && mAllChildren[index].getParent() != null) { + if (view.getParent() != null && !mChildrenRemovedWhileTransitioning.contains(view.getId())) { int clippedSoFar = 0; for (int i = 0; i < index; i++) { - if (mAllChildren[i].getParent() == null) { + if (mAllChildren[i].getParent() == null || mChildrenRemovedWhileTransitioning.contains(mAllChildren[i].getId())) { clippedSoFar++; } } removeViewsInLayout(index - clippedSoFar, 1); } removeFromArray(index); + } /*package*/ void removeAllViewsWithSubviewClippingEnabled() { From 150c15ef680a0de18d86b23e534eb2ec4242b24f Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Sun, 24 Nov 2024 01:12:48 +0100 Subject: [PATCH 03/12] Cleanup --- .../com/facebook/react/views/view/ReactClippingViewManager.kt | 1 - .../java/com/facebook/react/views/view/ReactViewGroup.java | 3 --- 2 files changed, 4 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt index a0ee071205cf..2f2453e97a1d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.kt @@ -67,7 +67,6 @@ public abstract class ReactClippingViewManager : ViewGroupMa } else { parent.removeViewAt(index) } - } override fun removeAllViews(parent: T) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index c78c2f3224c7..7b5983f2f2f4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -136,7 +136,6 @@ public void shutdown() { private boolean mIsTransitioning = false; private @Nullable Set mChildrenRemovedWhileTransitioning = null; - /** * Creates a new `ReactViewGroup` instance. * @@ -418,7 +417,6 @@ public void endViewTransition(View view) { super.endViewTransition(view); mIsTransitioning = false; if (mChildrenRemovedWhileTransitioning != null) { - mChildrenRemovedWhileTransitioning.clear(); mChildrenRemovedWhileTransitioning = null; } } @@ -707,7 +705,6 @@ public void run() { removeViewsInLayout(index - clippedSoFar, 1); } removeFromArray(index); - } /*package*/ void removeAllViewsWithSubviewClippingEnabled() { From 48b90adf998661ed40e00bbe428bdb23dd756ccb Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Sun, 24 Nov 2024 01:13:19 +0100 Subject: [PATCH 04/12] Cleanup 2 --- .../main/java/com/facebook/react/views/view/ReactViewGroup.java | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 7b5983f2f2f4..0acf1f5cbbc2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -421,7 +421,6 @@ public void endViewTransition(View view) { } } - private void updateClippingToRect(Rect clippingRect) { Assertions.assertNotNull(mAllChildren); int clippedSoFar = 0; From 6e153525f9f8e03b94aea44fb3641395fc6f2965 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Sun, 24 Nov 2024 01:13:54 +0100 Subject: [PATCH 05/12] Cleanup 3 --- .../main/java/com/facebook/react/views/view/ReactViewGroup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 0acf1f5cbbc2..b32487495092 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -689,8 +689,8 @@ public void run() { Assertions.assertCondition(mRemoveClippedSubviews); Assertions.assertNotNull(mClippingRect); Assertions.assertNotNull(mChildrenRemovedWhileTransitioning); - View[] childArray = Assertions.assertNotNull(mAllChildren); + view.removeOnLayoutChangeListener(mChildrenLayoutChangeListener); int index = indexOfChildInAllChildren(view); From 4d6b7962882c5fa59cba5a94785b78bbe93cbda5 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Sun, 24 Nov 2024 01:18:15 +0100 Subject: [PATCH 06/12] Prevent bug when setting removeClippedSubviews to `false` after `endViewTransition` call --- .../main/java/com/facebook/react/views/view/ReactViewGroup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index b32487495092..02081fdef618 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -417,7 +417,7 @@ public void endViewTransition(View view) { super.endViewTransition(view); mIsTransitioning = false; if (mChildrenRemovedWhileTransitioning != null) { - mChildrenRemovedWhileTransitioning = null; + mChildrenRemovedWhileTransitioning.clear(); } } From 93b0a3547c1ad5bb713383e015d9f110863f43e6 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Sun, 24 Nov 2024 11:11:00 +0100 Subject: [PATCH 07/12] Add missing import --- .../java/com/facebook/react/views/view/ReactViewGroup.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 02081fdef618..48f29f386554 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -56,6 +56,9 @@ import com.facebook.react.uimanager.style.LogicalEdge; import com.facebook.react.uimanager.style.Overflow; +import java.util.HashSet; +import java.util.Set; + /** * Backing for a React View. Has support for borders, but since borders aren't common, lazy * initializes most of the storage needed for them. From c3da8d0987ce97bc5bb21915c25b43c3d4f76d3f Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Tue, 26 Nov 2024 15:16:49 +0100 Subject: [PATCH 08/12] Allocate hashset only when necessary --- .../react/views/view/ReactViewGroup.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 48f29f386554..8de52e7bc675 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -365,14 +365,12 @@ public void setRemoveClippedSubviews(boolean removeClippedSubviews) { mAllChildren[i] = child; child.addOnLayoutChangeListener(mChildrenLayoutChangeListener); } - mChildrenRemovedWhileTransitioning = new HashSet<>(); updateClippingRect(); } else { // Add all clipped views back, deallocate additional arrays, remove layoutChangeListener Assertions.assertNotNull(mClippingRect); Assertions.assertNotNull(mAllChildren); Assertions.assertNotNull(mChildrenLayoutChangeListener); - Assertions.assertNotNull(mChildrenRemovedWhileTransitioning); for (int i = 0; i < mAllChildrenCount; i++) { mAllChildren[i].removeOnLayoutChangeListener(mChildrenLayoutChangeListener); } @@ -382,7 +380,6 @@ public void setRemoveClippedSubviews(boolean removeClippedSubviews) { mClippingRect = null; mAllChildrenCount = 0; mChildrenLayoutChangeListener = null; - mChildrenRemovedWhileTransitioning = null; } } @@ -409,7 +406,7 @@ public void updateClippingRect() { updateClippingToRect(mClippingRect); } - @Override + @Override public void startViewTransition(View view) { super.startViewTransition(view); mIsTransitioning = true; @@ -420,8 +417,15 @@ public void endViewTransition(View view) { super.endViewTransition(view); mIsTransitioning = false; if (mChildrenRemovedWhileTransitioning != null) { - mChildrenRemovedWhileTransitioning.clear(); + mChildrenRemovedWhileTransitioning = null; + } + } + + public Set ensureChildrenRemovedWhileTransitioning() { + if (mChildrenRemovedWhileTransitioning == null) { + mChildrenRemovedWhileTransitioning = new HashSet<>(); } + return mChildrenRemovedWhileTransitioning; } private void updateClippingToRect(Rect clippingRect) { @@ -571,8 +575,8 @@ public void onViewRemoved(View child) { setChildrenDrawingOrderEnabled(false); } - if (mIsTransitioning && mChildrenRemovedWhileTransitioning != null) { - mChildrenRemovedWhileTransitioning.add(child.getId()); + if (mIsTransitioning) { + ensureChildrenRemovedWhileTransitioning().add(child.getId()); } super.onViewRemoved(child); @@ -691,7 +695,6 @@ public void run() { UiThreadUtil.assertOnUiThread(); Assertions.assertCondition(mRemoveClippedSubviews); Assertions.assertNotNull(mClippingRect); - Assertions.assertNotNull(mChildrenRemovedWhileTransitioning); View[] childArray = Assertions.assertNotNull(mAllChildren); view.removeOnLayoutChangeListener(mChildrenLayoutChangeListener); From eb4e4fde23eaeddc09de52f1c021c394c9a52f26 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Wed, 27 Nov 2024 10:47:18 +0100 Subject: [PATCH 09/12] Get rid of redundant null check --- .../java/com/facebook/react/views/view/ReactViewGroup.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 577579e4f323..696f28204e19 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -420,9 +420,7 @@ public void startViewTransition(View view) { public void endViewTransition(View view) { super.endViewTransition(view); mIsTransitioning = false; - if (mChildrenRemovedWhileTransitioning != null) { - mChildrenRemovedWhileTransitioning = null; - } + mChildrenRemovedWhileTransitioning = null; } public Set ensureChildrenRemovedWhileTransitioning() { From c14e0268fcc10a78bb60fa65a274f34b14e808c2 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Wed, 27 Nov 2024 16:31:58 +0100 Subject: [PATCH 10/12] Review part one --- .../facebook/react/views/view/ReactViewGroup.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 696f28204e19..00296ac6f454 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -60,9 +60,6 @@ import java.util.HashSet; import java.util.Set; -import java.util.HashSet; -import java.util.Set; - /** * Backing for a React View. Has support for borders, but since borders aren't common, lazy * initializes most of the storage needed for them. @@ -140,8 +137,8 @@ public void shutdown() { private @Nullable ViewGroupDrawingOrderHelper mDrawingOrderHelper; private float mBackfaceOpacity; private String mBackfaceVisibility; - private boolean mIsTransitioning = false; - private @Nullable Set mChildrenRemovedWhileTransitioning = null; + private boolean mIsTransitioning; + private @Nullable Set mChildrenRemovedWhileTransitioning; /** * Creates a new `ReactViewGroup` instance. @@ -175,6 +172,8 @@ private void initView() { mDrawingOrderHelper = null; mBackfaceOpacity = 1.f; mBackfaceVisibility = "visible"; + mIsTransitioning = false; + mChildrenRemovedWhileTransitioning = null; } /* package */ void recycleView() { @@ -423,7 +422,7 @@ public void endViewTransition(View view) { mChildrenRemovedWhileTransitioning = null; } - public Set ensureChildrenRemovedWhileTransitioning() { + private Set ensureChildrenRemovedWhileTransitioning() { if (mChildrenRemovedWhileTransitioning == null) { mChildrenRemovedWhileTransitioning = new HashSet<>(); } @@ -709,12 +708,11 @@ public void run() { /*package*/ void removeViewWithSubviewClippingEnabled(View view) { UiThreadUtil.assertOnUiThread(); + Assertions.assertCondition(mRemoveClippedSubviews); Assertions.assertNotNull(mClippingRect); View[] childArray = Assertions.assertNotNull(mAllChildren); - view.removeOnLayoutChangeListener(mChildrenLayoutChangeListener); - int index = indexOfChildInAllChildren(view); if (!isViewClipped(childArray[index])) { int clippedSoFar = 0; From a7c7af3eaaa2879c9d4f086d3aa6063b89b940be Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Wed, 27 Nov 2024 16:35:17 +0100 Subject: [PATCH 11/12] Just clear the hash set, do not release it --- .../java/com/facebook/react/views/view/ReactViewGroup.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 00296ac6f454..311588c37d52 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -419,7 +419,9 @@ public void startViewTransition(View view) { public void endViewTransition(View view) { super.endViewTransition(view); mIsTransitioning = false; - mChildrenRemovedWhileTransitioning = null; + if (mChildrenRemovedWhileTransitioning != null) { + mChildrenRemovedWhileTransitioning.clear(); + } } private Set ensureChildrenRemovedWhileTransitioning() { From f54164d809fc5b434ee36ad4677a2705b59349c1 Mon Sep 17 00:00:00 2001 From: Kacper Kafara Date: Mon, 2 Dec 2024 13:11:36 +0100 Subject: [PATCH 12/12] Support cases where not all children are transitioning at once --- .../react/views/view/ReactViewGroup.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 311588c37d52..2b462cfd1956 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -137,7 +137,6 @@ public void shutdown() { private @Nullable ViewGroupDrawingOrderHelper mDrawingOrderHelper; private float mBackfaceOpacity; private String mBackfaceVisibility; - private boolean mIsTransitioning; private @Nullable Set mChildrenRemovedWhileTransitioning; /** @@ -172,7 +171,6 @@ private void initView() { mDrawingOrderHelper = null; mBackfaceOpacity = 1.f; mBackfaceVisibility = "visible"; - mIsTransitioning = false; mChildrenRemovedWhileTransitioning = null; } @@ -409,18 +407,11 @@ public void updateClippingRect() { updateClippingToRect(mClippingRect); } - @Override - public void startViewTransition(View view) { - super.startViewTransition(view); - mIsTransitioning = true; - } - @Override public void endViewTransition(View view) { super.endViewTransition(view); - mIsTransitioning = false; if (mChildrenRemovedWhileTransitioning != null) { - mChildrenRemovedWhileTransitioning.clear(); + mChildrenRemovedWhileTransitioning.remove(view.getId()); } } @@ -431,6 +422,10 @@ private Set ensureChildrenRemovedWhileTransitioning() { return mChildrenRemovedWhileTransitioning; } + private boolean isChildRemovedWhileTransitioning(View child) { + return mChildrenRemovedWhileTransitioning != null && mChildrenRemovedWhileTransitioning.contains(child.getId()); + } + private void updateClippingToRect(Rect clippingRect) { Assertions.assertNotNull(mAllChildren); int clippedSoFar = 0; @@ -591,7 +586,8 @@ public void onViewRemoved(View child) { setChildrenDrawingOrderEnabled(false); } - if (mIsTransitioning) { + // The parent might not be null in case the child is transitioning. + if (child.getParent() != null) { ensureChildrenRemovedWhileTransitioning().add(child.getId()); } @@ -744,7 +740,7 @@ public void run() { private boolean isViewClipped(View view) { ViewParent parent = view.getParent(); - if (parent == null || (mChildrenRemovedWhileTransitioning != null && mChildrenRemovedWhileTransitioning.contains(view.getId()))) { + if (parent == null || isChildRemovedWhileTransitioning(view)) { return true; } else { Assertions.assertCondition(parent == this);