Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subviews layer transform and layoutSubviews

my question is related to

UIView/CALayer: Transform triggers layoutSubviews in superview

Where is reported that, from a TSI reply from apple:

Generally, changing a geometric property of a view (or layer) will trigger a cascade of layout invalidations up the view hierarchy because parent views may have Auto Layout constraints involving the modified child. Note that Auto Layout is active in some form regardless of whether you have explicitly enabled it.

In my case i have a very simple view hierarchy where view A contains view B

In the layoutSubviews of A i'm setting the frame of B.

When I perform animations (transform and opacity) on the backing layer of B, sometimes, layoutSubviews of A is called. This is obviously a problem because i'm setting the frame of B in the layoutSubviews of A and this break the animation.

How can I avoid this conflict between the layout of B and the animation?

like image 578
Luca Bartoletti Avatar asked Dec 05 '22 05:12

Luca Bartoletti


1 Answers

I discovered that is possible to solve this problem in many ways:

1) Temporary save the transform, change the frame and than reapply the transform:

[super layoutSubviews];

//backup the transform value before the layout
CATransform3D transform = self.internalView.layer.transform;

//Set identity and update all the necessary frames
self.internalView.layer.transform = CATransform3DIdentity;
self.internalView.frame = self.bounds;

//set back the transform
self.internalView.layer.transform = transform;

2) Change the bounds and the center of the view without touch the frame. Bounds and center seems to not affect the transform. Make sense because the frame is calculated internally reading layer's bounds, position, transform, anchor point.

self.internalView.bounds = self.bounds;
self.internalView.center = CGPointMake(floorf(CGRectGetWidth(self.bounds)/2.0f),        floorf(CGRectGetHeight(self.bounds)/2.0f));

3) Apple in a TSI (reported here UIView/CALayer: Transform triggers layoutSubviews in superview) suggests to

"Wrap your cell contents in an intermediate view. When you modify the transform of this intermediate view, only the cell's layout should be invalidated, so your expensive layout method won't be called.

If that doesn't work, create some mechanism to signal to your expensive layout method when it actually does (or does not) have to do work. This could be a property you set when the only changes you make are to the transforms."

4) I also experimented turning off completely autolayout for the subviews of my custom view. You can read this really good article from obj.io where is explained that if you remove the call to [super layoutSubviews] from the layoutSubviews implementation you are opting out autolayout for your custom view and all its subviews.

The tread off is that you must be aware that in the case you add as subview a view with constrains the autolayout system will rise an exception like this:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. MyView's implementation of -layoutSubviews needs to call super.'

The solution 1 and 2 are good if you have a simple layout logic. If your layout logic is expansive you can implement 3 or 4 and referee to this other question UIView/CALayer: Transform triggers layoutSubviews in superview

like image 91
Luca Bartoletti Avatar answered Dec 11 '22 10:12

Luca Bartoletti