diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 686ce6e0f7366b..c44d4446a77705 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -7829,8 +7829,6 @@ public class com/facebook/react/views/view/ReactDrawableHelper { public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGroup, com/facebook/react/touch/ReactHitSlopView, com/facebook/react/touch/ReactInterceptingViewGroup, com/facebook/react/uimanager/ReactClippingViewGroup, com/facebook/react/uimanager/ReactOverflowViewWithInset, com/facebook/react/uimanager/ReactPointerEventsView, com/facebook/react/uimanager/ReactZIndexedViewGroup { public fun (Landroid/content/Context;)V - public fun addView (Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;)V - protected fun addViewInLayout (Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;Z)Z protected fun dispatchDraw (Landroid/graphics/Canvas;)V public fun dispatchGenericMotionEvent (Landroid/view/MotionEvent;)Z public fun dispatchProvideStructure (Landroid/view/ViewStructure;)V @@ -7838,7 +7836,6 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro public fun draw (Landroid/graphics/Canvas;)V protected fun drawChild (Landroid/graphics/Canvas;Landroid/view/View;J)Z protected fun getChildDrawingOrder (II)I - public fun getChildVisibleRect (Landroid/view/View;Landroid/graphics/Rect;Landroid/graphics/Point;)Z public fun getClippingRect (Landroid/graphics/Rect;)V public fun getHitSlopRect ()Landroid/graphics/Rect; public fun getOverflow ()Ljava/lang/String; @@ -7854,11 +7851,8 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro protected fun onMeasure (II)V protected fun onSizeChanged (IIII)V public fun onTouchEvent (Landroid/view/MotionEvent;)Z - public fun removeView (Landroid/view/View;)V - public fun removeViewAt (I)V - public fun removeViewInLayout (Landroid/view/View;)V - public fun removeViews (II)V - public fun removeViewsInLayout (II)V + public fun onViewAdded (Landroid/view/View;)V + public fun onViewRemoved (Landroid/view/View;)V public fun requestLayout ()V public fun setBackfaceVisibility (Ljava/lang/String;)V public fun setBackfaceVisibilityDependantOpacity ()V 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 2064fc00afd934..7dcf9aadba8f48 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 @@ -17,7 +17,6 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Path; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; @@ -54,7 +53,6 @@ import com.facebook.react.uimanager.ViewGroupDrawingOrderHelper; import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.common.ViewUtil; -import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable; import com.facebook.react.uimanager.style.BorderRadiusProp; import com.facebook.react.uimanager.style.BorderStyle; import com.facebook.react.uimanager.style.LogicalEdge; @@ -131,13 +129,11 @@ public void shutdown() { private @Nullable Rect mClippingRect; private @Nullable Rect mHitSlopRect; private Overflow mOverflow; - private PointerEvents mPointerEvents; + private PointerEvents mPointerEvents = PointerEvents.AUTO; private @Nullable ChildrenLayoutChangeListener mChildrenLayoutChangeListener; - private @Nullable CSSBackgroundDrawable mCSSBackgroundDrawable; private @Nullable OnInterceptTouchEventListener mOnInterceptTouchEventListener; private boolean mNeedsOffscreenAlphaCompositing; private @Nullable ViewGroupDrawingOrderHelper mDrawingOrderHelper; - private @Nullable Path mPath; private float mBackfaceOpacity; private String mBackfaceVisibility; @@ -168,11 +164,9 @@ private void initView() { mOverflow = Overflow.VISIBLE; mPointerEvents = PointerEvents.AUTO; mChildrenLayoutChangeListener = null; - mCSSBackgroundDrawable = null; mOnInterceptTouchEventListener = null; mNeedsOffscreenAlphaCompositing = false; mDrawingOrderHelper = null; - mPath = null; mBackfaceOpacity = 1.f; mBackfaceVisibility = "visible"; } @@ -266,7 +260,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { } @Override - public boolean onTouchEvent(MotionEvent ev) { + public boolean onTouchEvent(MotionEvent event) { // We do not accept the touch event if this view is not supposed to receive it. if (!PointerEvents.canBeTouchTarget(mPointerEvents)) { return false; @@ -430,7 +424,7 @@ private void updateClippingToRect(Rect clippingRect) { + mRecycleCount, e); } - if (mAllChildren[i].getParent() == null) { + if (isViewClipped(mAllChildren[i])) { clippedSoFar++; } } @@ -452,12 +446,12 @@ private void updateSubviewClipStatus(Rect clippingRect, int idx, int clippedSoFa // it won't be size and located properly. Animation animation = child.getAnimation(); boolean isAnimating = animation != null && !animation.hasEnded(); - if (!intersects && child.getParent() != null && !isAnimating) { + if (!intersects && !isViewClipped(child) && !isAnimating) { // We can try saving on invalidate call here as the view that we remove is out of visible area // therefore invalidation is not necessary. removeViewInLayout(child); needUpdateClippingRecursive = true; - } else if (intersects && child.getParent() == null) { + } else if (intersects && isViewClipped(child)) { addViewInLayout(child, idx - clippedSoFar, sDefaultLayoutParam, true); invalidate(); needUpdateClippingRecursive = true; @@ -489,7 +483,7 @@ private void updateSubviewClipStatus(View subview) { subview.getLeft(), subview.getTop(), subview.getRight(), subview.getBottom()); // If it was intersecting before, should be attached to the parent - boolean oldIntersects = (subview.getParent() != null); + boolean oldIntersects = !isViewClipped(subview); if (intersects != oldIntersects) { int clippedSoFar = 0; @@ -498,18 +492,13 @@ private void updateSubviewClipStatus(View subview) { updateSubviewClipStatus(mClippingRect, i, clippedSoFar); break; } - if (mAllChildren[i].getParent() == null) { + if (isViewClipped(mAllChildren[i])) { clippedSoFar++; } } } } - @Override - public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { - return super.getChildVisibleRect(child, r, offset); - } - @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); @@ -535,83 +524,33 @@ private boolean customDrawOrderDisabled() { return ViewUtil.getUIManagerType(getId()) == UIManagerType.FABRIC; } - private void handleAddView(View view) { + @Override + public void onViewAdded(View child) { UiThreadUtil.assertOnUiThread(); if (!customDrawOrderDisabled()) { - getDrawingOrderHelper().handleAddView(view); + getDrawingOrderHelper().handleAddView(child); setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); } else { setChildrenDrawingOrderEnabled(false); } + super.onViewAdded(child); } - private void handleRemoveView(@Nullable View view) { + @Override + public void onViewRemoved(View child) { UiThreadUtil.assertOnUiThread(); if (!customDrawOrderDisabled()) { - if (indexOfChild(view) == -1) { + if (indexOfChild(child) == -1) { return; } - getDrawingOrderHelper().handleRemoveView(view); + getDrawingOrderHelper().handleRemoveView(child); setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); } else { setChildrenDrawingOrderEnabled(false); } - } - - private void handleRemoveViews(int start, int count) { - int endIndex = start + count; - for (int index = start; index < endIndex; index++) { - if (index < getChildCount()) { - handleRemoveView(getChildAt(index)); - } - } - } - - @Override - public void addView(View child, int index, @Nullable ViewGroup.LayoutParams params) { - // This will get called for every overload of addView so there is not need to override every - // method. - handleAddView(child); - super.addView(child, index, params); - } - - @Override - protected boolean addViewInLayout( - View child, int index, LayoutParams params, boolean preventRequestLayout) { - handleAddView(child); - return super.addViewInLayout(child, index, params, preventRequestLayout); - } - - @Override - public void removeView(@Nullable View view) { - handleRemoveView(view); - super.removeView(view); - } - - @Override - public void removeViewAt(int index) { - handleRemoveView(getChildAt(index)); - super.removeViewAt(index); - } - - @Override - public void removeViewInLayout(View view) { - handleRemoveView(view); - super.removeViewInLayout(view); - } - - @Override - public void removeViewsInLayout(int start, int count) { - handleRemoveViews(start, count); - super.removeViewsInLayout(start, count); - } - - @Override - public void removeViews(int start, int count) { - handleRemoveViews(start, count); - super.removeViews(start, count); + super.onViewRemoved(child); } @Override @@ -685,18 +624,18 @@ View getChildAtWithSubviewClippingEnabled(int index) { /*package*/ void addViewWithSubviewClippingEnabled( final View child, int index, ViewGroup.LayoutParams params) { Assertions.assertCondition(mRemoveClippedSubviews); - Assertions.assertNotNull(mClippingRect); - Assertions.assertNotNull(mAllChildren); + Rect clippingRect = Assertions.assertNotNull(mClippingRect); + View[] childArray = Assertions.assertNotNull(mAllChildren); addInArray(child, index); // we add view as "clipped" and then run {@link #updateSubviewClipStatus} to conditionally // attach it int clippedSoFar = 0; for (int i = 0; i < index; i++) { - if (mAllChildren[i].getParent() == null) { + if (isViewClipped(childArray[i])) { clippedSoFar++; } } - updateSubviewClipStatus(mClippingRect, index, clippedSoFar); + updateSubviewClipStatus(clippingRect, index, clippedSoFar); child.addOnLayoutChangeListener(mChildrenLayoutChangeListener); if (child instanceof ReactClippingProhibitedView) { @@ -728,13 +667,13 @@ public void run() { Assertions.assertCondition(mRemoveClippedSubviews); Assertions.assertNotNull(mClippingRect); - Assertions.assertNotNull(mAllChildren); + View[] childArray = Assertions.assertNotNull(mAllChildren); view.removeOnLayoutChangeListener(mChildrenLayoutChangeListener); int index = indexOfChildInAllChildren(view); - if (mAllChildren[index].getParent() != null) { + if (!isViewClipped(childArray[index])) { int clippedSoFar = 0; for (int i = 0; i < index; i++) { - if (mAllChildren[i].getParent() == null) { + if (isViewClipped(childArray[i])) { clippedSoFar++; } } @@ -745,19 +684,26 @@ public void run() { /*package*/ void removeAllViewsWithSubviewClippingEnabled() { Assertions.assertCondition(mRemoveClippedSubviews); - Assertions.assertNotNull(mAllChildren); + View[] childArray = Assertions.assertNotNull(mAllChildren); for (int i = 0; i < mAllChildrenCount; i++) { - mAllChildren[i].removeOnLayoutChangeListener(mChildrenLayoutChangeListener); + childArray[i].removeOnLayoutChangeListener(mChildrenLayoutChangeListener); } removeAllViewsInLayout(); mAllChildrenCount = 0; } + /** + * @return {@code true} if the view has been removed from the ViewGroup. + */ + private boolean isViewClipped(View view) { + return view.getParent() == null; + } + private int indexOfChildInAllChildren(View child) { final int count = mAllChildrenCount; - final View[] children = Assertions.assertNotNull(mAllChildren); + final View[] childArray = Assertions.assertNotNull(mAllChildren); for (int i = 0; i < count; i++) { - if (children[i] == child) { + if (childArray[i] == child) { return i; } } @@ -765,26 +711,26 @@ private int indexOfChildInAllChildren(View child) { } private void addInArray(View child, int index) { - View[] children = Assertions.assertNotNull(mAllChildren); + View[] childArray = Assertions.assertNotNull(mAllChildren); final int count = mAllChildrenCount; - final int size = children.length; + final int size = childArray.length; if (index == count) { if (size == count) { mAllChildren = new View[size + ARRAY_CAPACITY_INCREMENT]; - System.arraycopy(children, 0, mAllChildren, 0, size); - children = mAllChildren; + System.arraycopy(childArray, 0, mAllChildren, 0, size); + childArray = mAllChildren; } - children[mAllChildrenCount++] = child; + childArray[mAllChildrenCount++] = child; } else if (index < count) { if (size == count) { mAllChildren = new View[size + ARRAY_CAPACITY_INCREMENT]; - System.arraycopy(children, 0, mAllChildren, 0, index); - System.arraycopy(children, index, mAllChildren, index + 1, count - index); - children = mAllChildren; + System.arraycopy(childArray, 0, mAllChildren, 0, index); + System.arraycopy(childArray, index, mAllChildren, index + 1, count - index); + childArray = mAllChildren; } else { - System.arraycopy(children, index, children, index + 1, count - index); + System.arraycopy(childArray, index, childArray, index + 1, count - index); } - children[index] = child; + childArray[index] = child; mAllChildrenCount++; } else { throw new IndexOutOfBoundsException("index=" + index + " count=" + count); @@ -792,13 +738,13 @@ private void addInArray(View child, int index) { } private void removeFromArray(int index) { - final View[] children = Assertions.assertNotNull(mAllChildren); + final View[] childArray = Assertions.assertNotNull(mAllChildren); final int count = mAllChildrenCount; if (index == count - 1) { - children[--mAllChildrenCount] = null; + childArray[--mAllChildrenCount] = null; } else if (index >= 0 && index < count) { - System.arraycopy(children, index + 1, children, index, count - index - 1); - children[--mAllChildrenCount] = null; + System.arraycopy(childArray, index + 1, childArray, index, count - index - 1); + childArray[--mAllChildrenCount] = null; } else { throw new IndexOutOfBoundsException(); }