diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java index 9114a8cf6..02095d7a6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java @@ -393,12 +393,13 @@ import com.facebook.react.touch.JSResponderHandler; if (view instanceof ViewGroup && viewManager instanceof ViewGroupManager) { ViewGroup viewGroup = (ViewGroup) view; ViewGroupManager viewGroupManager = (ViewGroupManager) viewManager; - for (int i = 0; i < viewGroupManager.getChildCount(viewGroup); i++) { + for (int i = viewGroupManager.getChildCount(viewGroup) - 1; i >= 0; i--) { View child = viewGroupManager.getChildAt(viewGroup, i); if (mTagsToViews.get(child.getId()) != null) { dropView(child); } } + viewGroupManager.removeAllViews(viewGroup); } mTagsToViews.remove(view.getId()); mTagsToViewManagers.remove(view.getId()); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java index 9443d98ff..d9ee6d8b5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java @@ -122,16 +122,7 @@ public class ReactShadowNode extends CSSNode { int increase = node.mIsLayoutOnly ? node.mTotalNativeChildren : 1; mTotalNativeChildren += increase; - if (mIsLayoutOnly) { - ReactShadowNode parent = getParent(); - while (parent != null) { - parent.mTotalNativeChildren += increase; - if (!parent.mIsLayoutOnly) { - break; - } - parent = parent.getParent(); - } - } + updateNativeChildrenCountInParent(increase); } @Override @@ -141,17 +132,31 @@ public class ReactShadowNode extends CSSNode { int decrease = removed.mIsLayoutOnly ? removed.mTotalNativeChildren : 1; mTotalNativeChildren -= decrease; + updateNativeChildrenCountInParent(-decrease); + return removed; + } + + public void removeAllChildren() { + for (int i = getChildCount() - 1; i >= 0; i--) { + super.removeChildAt(i); + } + markUpdated(); + + updateNativeChildrenCountInParent(-mTotalNativeChildren); + mTotalNativeChildren = 0; + } + + private void updateNativeChildrenCountInParent(int delta) { if (mIsLayoutOnly) { ReactShadowNode parent = getParent(); while (parent != null) { - parent.mTotalNativeChildren -= decrease; + parent.mTotalNativeChildren -= delta; if (!parent.mIsLayoutOnly) { break; } parent = parent.getParent(); } } - return removed; } /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 896e13c01..12cae1712 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -406,9 +406,10 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements private void removeCSSNode(int tag) { ReactShadowNode node = mShadowNodeRegistry.getNode(tag); mShadowNodeRegistry.removeNode(tag); - for (int i = 0;i < node.getChildCount(); i++) { + for (int i = node.getChildCount() - 1; i >= 0; i--) { removeCSSNode(node.getChildAt(i).getReactTag()); } + node.removeAllChildren(); } /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java index 646f86772..4091eb8d8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java @@ -48,6 +48,12 @@ public abstract class ViewGroupManager parent.removeViewAt(index); } + public void removeAllViews(T parent) { + for (int i = getChildCount(parent) - 1; i >= 0; i--) { + removeViewAt(parent, i); + } + } + /** * Returns whether this View type needs to handle laying out its own children instead of * deferring to the standard css-layout algorithm. diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 6131f0051..134b6492b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -403,6 +403,16 @@ public class ReactViewGroup extends ViewGroup implements removeFromArray(index); } + /*package*/ void removeAllViewsWithSubviewClippingEnabled() { + Assertions.assertCondition(mRemoveClippedSubviews); + Assertions.assertNotNull(mAllChildren); + for (int i = 0; i < mAllChildrenCount; i++) { + mAllChildren[i].removeOnLayoutChangeListener(mChildrenLayoutChangeListener); + } + removeAllViewsInLayout(); + mAllChildrenCount = 0; + } + private int indexOfChildInAllChildren(View child) { final int count = mAllChildrenCount; final View[] children = Assertions.assertNotNull(mAllChildren); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index 712d7dc3d..12c691a61 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -207,4 +207,14 @@ public class ReactViewManager extends ViewGroupManager { parent.removeViewAt(index); } } + + @Override + public void removeAllViews(ReactViewGroup parent) { + boolean removeClippedSubviews = parent.getRemoveClippedSubviews(); + if (removeClippedSubviews) { + parent.removeAllViewsWithSubviewClippingEnabled(); + } else { + parent.removeAllViews(); + } + } }