I have a very simple UIImageView
which is contained in a container view. They are the same size, no auto layout used. When user presses a button, UIImageView
should be rotated by 90 degrees. When UIImageView
(not UIImageView.image
) is rotated it should fit its superview (.ScaleAspectFit
).
So far I've figured out the easiest part: transform rotation.
self.currentRotation += 90
if self.currentRotation >= 360 {
self.currentRotation = 0
}
let angleInRadians: Double
switch self.currentRotation {
case 0:
angleInRadians = 0
case 90:
angleInRadians = M_PI_2
case 180:
angleInRadians = M_PI
case 270:
angleInRadians = M_PI + M_PI_2
default:
angleInRadians = 0
break;
}
let newTransform = CGAffineTransformRotate(CGAffineTransformIdentity, CGFloat(angleInRadians))
By getting some information from this question, I was able to write Swift versions of helper extensions, but I still can't figure out how to find UIImageView's frame.
extension UIView {
var originalFrame: CGRect {
let currentTransform = self.transform
self.transform = CGAffineTransformIdentity
let originalFrame = self.frame
self.transform = currentTransform
return originalFrame
}
var transformedTopLeftPoint: CGPoint {
return self.transformedPointForOriginalPoint(originalFrame.topLeftPoint)
}
var transformedTopRightPoint: CGPoint {
return self.transformedPointForOriginalPoint(originalFrame.topRightPoint)
}
var transformedBottomLeftPoint: CGPoint {
return self.transformedPointForOriginalPoint(originalFrame.bottomLeftPoint)
}
var transformedBottomRightPoint: CGPoint {
return self.transformedPointForOriginalPoint(originalFrame.bottomRightPoint)
}
// helper to get point offset from center
func centerOffset(point: CGPoint) -> CGPoint {
return CGPoint(x: point.x - self.center.x, y: point.y - self.center.y)
}
// helper to get point back relative to center
func pointRelativeToCenter(point: CGPoint) -> CGPoint {
return CGPoint(x: point.x + self.center.x, y: point.y + self.center.y)
}
// helper to get point relative to transformed coords
func transformedPointForOriginalPoint(point: CGPoint) -> CGPoint {
// get offset from center
let offset = self.centerOffset(point)
// get transformed point
let transformedPoint = CGPointApplyAffineTransform(offset, self.transform)
// make relative to center
return self.pointRelativeToCenter(transformedPoint)
}
}
extension CGRect {
var topLeftPoint: CGPoint {
return self.origin
}
var topRightPoint: CGPoint {
return CGPoint(x: self.origin.x + self.size.width, y: self.origin.y)
}
var bottomLeftPoint: CGPoint {
return CGPoint(x: self.origin.x, y: self.origin.y + self.size.height)
}
var bottomRightPoint: CGPoint {
return CGPoint(x: self.origin.x + self.size.width, y: self.origin.y + self.size.height)
}
}
For better clarification, I'm attaching an image.
It shows a rotated view on top of its original frame (the smallest of the outlines) and the updated frame (the largest gray outline). The circles indicate the view's top-right corner before and after rotation. After the transform is applied, the frame updates to the minimum bounding box that encloses the view. Its new origin (the top-left corner of the gray outside box) has essentially nothing to do with the original view origin (the top-left corner of the black unrotated inner box). iOS does not provide a way to retrieve that adjusted point. Here are a series of view methods that perform that math for you. (UIView extension above)
I need to find the gray box's frame. But even with those methods I still can't figure out how to do that. What's the formula/algorithm to achieve what I want?