2015-11-02 58 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