开发者

Get size of UIView after applying CGAffineTransform

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 contai开发者_StackOverflowns the dimensions of the view with the transformation applied Thanks again to drawnonward


I use this in Objective C:

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

or in Swift 4:

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


[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.


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.


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


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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜