I have a UIView that may have scale and/or rotation transforms applied to it. My controller creates a new controller and passes the view to it. The new controller creates a new view and tries to place it in the same location and rotation as the passed view. It sets the location and size by converting the original view’s frame:
CGRect frame = [self.view convertRect:fromView.frame fromView:fromView.superview];
ImageScrollView *isv = [[ImageScrollView alloc]initWithFrame:frame image:image];
This works great, with the scaled size and location copied perfectly. However, if there is a rotation transform applied to fromView, it does not transfer.
So I added this line:
isv.transform = fromView.transform;
That nicely handles transfers the rotation, but also the scale transform. The result is that the scale transform is effectively applied twice, so the resulting view is much too large.
So how do I go about transferring the location (origin), scale, and rotation from one view to another, without doubling the scale?
Edit
Here is a more complete code example, where the original UIImageView (fromView) is being used to size and position a UIScrollView (the ImageScrollView subclass):
CGRect frame = [self.view convertRect:fromView.frame fromView:fromView.superview];
frame.origin.y += pagingScrollView.frame.origin.y;
ImageScrollView *isv = [[ImageScrollView alloc]initWithFrame:frame image:image];
isv.layer.anchorPoint = fromView.layer.anchorPoint;
isv.transform = fromView.transform;
isv.bounds = fromView.bounds;
isv.center = [self.view convertPoint:fromView.center fromView:fromView.superview];
[self.view insertSubview:isv belowSubview:captionView];
And here is the entirety of the configuration in ImageScrollView:
- (id)initWithFrame:(CGRect)frame image:(UIImage *)image {
if (self = [self initWithFrame:frame]) {
CGRect rect = CGRectMake(0, 0, frame.size.width, frame.size.height);
imageLoaded = YES;
imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = rect;
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
[self addSubview:imageView];
}
return self;
}
It looks as though the transform causes the imageView to scale up too large, as you can see in this ugly video.
Copy the first view’s
bounds,center, andtransformto the second view.Your code doesn’t work because
frameis a value that is derived from thebounds,center, andtransform. The setter forframetries to do the right thing by reversing the process, but it can’t always work correctly when a non-identitytransformis set.The documentation is pretty clear on this point: