From 5fbdc994f945ee8d834632649e3b82451660e8fe Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Fri, 9 Feb 2024 04:06:52 -0800 Subject: [PATCH] remove animation from borderLayer to stop unwanted animations (#42922) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/42922 changelog: [fix][ios] prevent unwanted border animation The problem: CALayer and its properties are animatable. If RN applies mutations inside an animation block, it will animate. In this particular example, it was animated because of a transition applied by the library and because we were not creating new views, but recycling views from previous screen. This caused size of _borderLayer to change from value A to value B inside of animation block. To resolve this, call removeAllAnimations on borderLayer. Reviewed By: cipolleschi Differential Revision: D53566886 fbshipit-source-id: 98e0b01a9185046e1ee500665c1832060ecc8884 --- .../View/RCTViewComponentView.mm | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index c9e551b96b6ef2..a015c450ee21b7 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -28,7 +28,7 @@ @implementation RCTViewComponentView { UIColor *_backgroundColor; - CALayer *_borderLayer; + __weak CALayer *_borderLayer; BOOL _needsInvalidateLayer; BOOL _isJSResponder; BOOL _removeClippedSubviews; @@ -404,9 +404,7 @@ - (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics _layoutMetrics = layoutMetrics; _needsInvalidateLayer = YES; - if (_borderLayer) { - _borderLayer.frame = self.layer.bounds; - } + _borderLayer.frame = self.layer.bounds; if (_contentView) { _contentView.frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame()); @@ -610,10 +608,7 @@ - (void)invalidateLayer if (useCoreAnimationBorderRendering) { layer.mask = nil; - if (_borderLayer) { - [_borderLayer removeFromSuperlayer]; - _borderLayer = nil; - } + [_borderLayer removeFromSuperlayer]; layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left; CGColorRef borderColor = RCTCreateCGColorRefFromSharedColor(borderMetrics.borderColors.left); @@ -626,11 +621,12 @@ - (void)invalidateLayer layer.backgroundColor = backgroundColor; } else { if (!_borderLayer) { - _borderLayer = [CALayer new]; - _borderLayer.zPosition = -1024.0f; - _borderLayer.frame = layer.bounds; - _borderLayer.magnificationFilter = kCAFilterNearest; - [layer addSublayer:_borderLayer]; + CALayer *borderLayer = [CALayer new]; + borderLayer.zPosition = -1024.0f; + borderLayer.frame = layer.bounds; + borderLayer.magnificationFilter = kCAFilterNearest; + [layer addSublayer:borderLayer]; + _borderLayer = borderLayer; } layer.backgroundColor = nil; @@ -671,6 +667,10 @@ - (void)invalidateLayer } } + // If mutations are applied inside of Animation block, it may cause _borderLayer to be animated. + // To stop that, imperatively remove all animations from _borderLayer. + [_borderLayer removeAllAnimations]; + // Stage 2.5. Custom Clipping Mask CAShapeLayer *maskLayer = nil; CGFloat cornerRadius = 0;