2015-11-02 52 views
2

我有一个非常简单的UIImageView它包含在容器视图中。它们大小相同,没有使用自动布局。当用户按下按钮时,UIImageView应该旋转90度。当UIImageView(不是UIImageView.image)被旋转时,它应该适合其超视图(.ScaleAspectFit)。 到目前为止,我已经想出了最简单的部分:转换旋转。如何在转换旋转后找到UIView的帧

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)) 

通过获得来自this question一些信息,我能写帮手扩展斯威夫特版本,但我仍然无法弄清楚如何找到的UIImageView的框架。

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) 
    } 
} 

为了更好的阐明,我附上了一张图片。

image for better understanding

它显示了在其原始帧(最小的 轮廓)和更新的帧(最大灰色轮廓)的顶部上的旋转视图。 圆圈表示在 之前和之后的视图的右上角。在应用变换之后,该帧将更新到围绕该视图的最小边界框 。它的新来源(灰色外框左上角的 )基本上与原始视图原点(黑色 未旋转的内框的左上角) 无关。 iOS不提供检索该调整点的方法。以下是一系列为您执行数学运算的视图方法。 (上面的UIView扩展名)

我需要找到灰框的框架。但即使采用这些方法,我仍然无法弄清楚如何做到这一点。什么是公式/算法来实现我想要的?

+0

简单。转换后的视图框架是该视图的边界框。所以只需使用框架。 – kirander

+0

@kirander但是,根据文档,当你设置一个自定义转换为UIView,框架属性变得不确定,不应该使用。 – xinatanil

+0

是的,这是真的,但提示是转换视图的框架描述最小的边界矩形。为什么不使用这个? – kirander

回答

2

转换后视图的转换centre保持不变。所以你需要根据中心来计算事情。例如:

func originalFrame() -> CGRect { 
    CGAffineTransform currentTransform = self.transform; 
    self.transform = CGAffineTransformIdentity; 
    let originalFrame = self.frame; 
    self.transform = currentTransform; 

    return originalFrame; 
} 

func centerOffset(point:CGPoint) -> CGPoint { 
    return CGPointMake(point.x - self.center.x, point.y - self.center.y); 
} 

func pointRelativeToCenter(point:CGPoint) -> CGPoint { 
    CGPointMake(point.x + self.center.x, point.y + self.center.y); 
} 


func newPointInView(point:CGPoint) -> CGPoint { 
    let offset = self.centerOffset(point) 
    let transformedPoint = CGPointApplyAffineTransform(offset, self.transform); 
    return self.pointRelativeToCenter(transformedPoint) 
} 

func newTopLeft() -> CGPoint { 
    let frame = self.originalFrame() 
    return self.newPointInView(frame) 
} 

func newTopRight() -> CGPoint { 
    let frame = self.originalFrame() 
    var point = frame.origin 
    point.x = point.x + frame.size.width 
    return self.newPointInView(point) 
} 


func newBottomLeft() -> CGPoint { 
    let frame = self.originalFrame() 
    var point = frame.origin 
    point.y = point.y + frame.size.height 
    return self.newPointInView(point) 
} 


func newBottomRight() -> CGPoint { 
    let frame = self.originalFrame() 
    var point = frame.origin 
    point.x = point.x + frame.size.width 
    point.y = point.y + frame.size.height 
    return self.newPointInView(point) 
} 

有关更多详细信息,请参阅此SO Thread

0

提示是转换视图的框架描述了最小的边界矩形。你可以使用它。

// after transform 
// obj-c 
CGRect boundingBoxFrame = myTransformedImageView.frame; 
+0

对不起,还是不明白。你是否建议通过将其边界与其他东西相结合来找到变换视图的框架?你能否提供一个代码示例?我有一个漫长的夜晚,我希望得到更详细的答案。 – xinatanil

+0

我编辑了答案。 – kirander

+0

感谢您的详细解答,它确实有效。但是,请你解释一下这种方法的危险性吗?根据文档“如果transform属性不是标识转换,frame属性的值是未定义的,因此应该忽略。“UIImageView的转换绝对不是CGAffineTransformIdentity,恐怕迟早我会找到另一种方法来计算转换后的视图的帧。 – xinatanil