Get size of UIView after applying CGAffineTransfor

2019-01-31 02:36发布

问题:

I was surprised not to find an answer to this question, maybe is something very simple I somehow overlook :

How to get the real size of an UIView after I apply a CGAffineTransform to it?

eg.

my UIView has size 300 x 200, I apply a scaling transform let's say factor 2 both horizontal and vertical, so the UIView now takes 600 x 400 on the screen, but it's bounds and it's layer's bounds are still returning a size of 300 x 200 ... where do I find the real size of the UIView ?

ps. forgot to mention I want to also rotate the uiview. If I apply only scaling CGSizeApplyAffineTransform works great, but when there's also rotation, then it does not work properly.

Edit: drawnonward pointed me in the right direction, I just refined a bit the code to compile and here it is :

UIView* view = (your view being transformed);
CGAffineTransform trans = (view.transform or create a new transformation);

CGRect rect = [view bounds];
CGMutablePathRef path = CGPathCreateMutable();
rect.origin = CGPointZero;
CGPathAddRect(path , &trans , rect);
rect = CGPathGetBoundingBox( path );
CGPathRelease( path );

Now rect.size contains the dimensions of the view with the transformation applied Thanks again to drawnonward

回答1:

[myView frame] returns the frame of the view as seen by the parent, for layout and relative sizes. [myView bounds] returns the bounds of the view as seen by itself, for drawing. If you have transforms applied to multiple views, you can use convertRect: to or from a view.

Edit:

Maybe something like this.

CGRect rect = [view bounds];
CGPathRef path = CGPathCreateMutable();
rect.origin = CGPointZero;
CGPathAddRect( rect , [view transform] );
rect = CGPathGetBoundingBox( path );
CGPathRelease( path );

The use [view center] to find the position in the superview.



回答2:

I use this in Objective C:

CGRect transformedBounds = CGRectApplyAffineTransform(view.bounds, view.transform);

or in Swift 4:

let transformedBounds = view.bounds.applying(view.transform)


回答3:

Use CGSizeApplyAffineTransform(size, transform) and it will return a transformed size. There are similar CGPoint and CGRect functions as well.



回答4:

Simpler: A view with (bounds) size s to which transform tr is applied has resulting size:

CGSizeMake(s.width*hypotf(tr.a, tr.b), s.height*hypotf(tr.c, tr.d))

However, if view's superview or any ancestor view has any non-unit transform applied, this size makes little sense in absolute terms.

If you want the absolute size of a view in window coordinates after any arbitrary transform has been applied to that view or its superviews, you should first compute the absolute transform matrix by composing all the view transform up to the root window, and then apply the above formula to the result.



回答5:

Old question, but bumped into here, after searching a solution and tons of attempts. It was simple;

view.layer.frame has all transformations applied and you'll get the size from view.layer.frame.size easily.

-- below here is not an answer to this question - -

And for my problem, I was trying to calculate new center value after changing layer.anchorPoint of my rotated view, so it doesn't move. And finally did it like this;

CGPoint topLeft = [self.superview convertPoint:CGPointMake(0, 0) fromView:self];
self.layer.anchorPoint = CGPointMake(0, 0);
self.center = topLeft;

for reverse

CGPoint center = [self.superview convertPoint:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2) fromView:self];
self.layer.anchorPoint = CGPointMake(.5, .5);
self.center = center;

finally.



回答6:

But you apply a rotating transform, it don't get right size by CGPathGetBoundingBox.