Search code examples
iosswiftuiviewautolayoutcore-graphics

Keeping autolayout after view transform(rotation) and resize(to bounds)


I have a view with circle subview on one corner of the view. I defined the circle's position by autolayout.

I need to rotate and resize the base view.

The problem is that if I rotate and then resize the view, position of the circle won't be where I expect it to be.

How do I keep layout in such a situation?


No resize or rotaion.

enter image description here


After rotation and resize

enter image description here

import UIKit

class ExampleController: UIViewController {

// UI Appearance

private let buttonWidth: CGFloat = 40
private var themeColor: UIColor = UIColor.magentaColor()



// Resizing and rotating view

let myView: UIView = {
    let v = UIView()
    v.layer.borderWidth = 1
    v.layer.borderColor = UIColor.magentaColor().CGColor

    v.frame = CGRectMake(100, 150, 150, 225)

    return v
}()

lazy var cornerButton: UIView = {
    let b = UIView()

    b.layer.cornerRadius = self.buttonWidth / 2
    b.layer.borderWidth  = 1
    b.layer.borderColor  = self.themeColor.CGColor

    return b
}()



// Control 

@IBOutlet weak var angleSlider: UISlider!
@IBOutlet weak var widthSlider: UISlider!




override func viewDidLoad() {
    super.viewDidLoad()

    setupSubviews()
}


func setupSubviews() {
    view.addSubview(myView)
    view.addSubview(angleSlider)


    // Angle Slider
    angleSlider.minimumValue = 0
    angleSlider.maximumValue = 360
    angleSlider.value        = 0

    // Width Slider
    widthSlider.maximumValue = Float(view!.frame.width)
    widthSlider.value        = Float(myView.frame.width)

    // Corner Button
    myView.addSubview( cornerButton )
    myView.addConstraintsWithFormat("H:[v0(\(buttonWidth))]", views: cornerButton) // Use extension to set width or height
    myView.addConstraintsWithFormat("V:[v0(\(buttonWidth))]", views: cornerButton) // Use extension to set width or height
    myView.addConstraint(NSLayoutConstraint(item: cornerButton, attribute: .CenterX, relatedBy: .Equal, toItem: myView, attribute: .Right, multiplier: 1, constant: 0))
    myView.addConstraint(NSLayoutConstraint(item: cornerButton, attribute: .CenterY, relatedBy: .Equal, toItem: myView, attribute: .Top,   multiplier: 1, constant: 0))
}







// Rotation

@IBAction func angleSliderDidChange(slider: UISlider) {
    print(slider.value)
    setAngle(forMyView: slider.value )
}

func setAngle(forMyView angle: Float) {
    let radian = angle.degreesToRadians
    myView.transform = CGAffineTransformMakeRotation( radian )
}





// Resize

@IBAction func widthSlider(sender: UISlider) {

    let newWidth: CGFloat = CGFloat(sender.value)

    let newSize = CGSizeMake(newWidth, myView.aspectRatioKeptHeight(forWidth: newWidth))
    myView.bounds.size = newSize

}


}

Solution

  • I solved the problem by myself.

    It was tricky but very simple.

    I stated changing bounds when the angle is 0 would not break the layout. This means I just had to temporary set angle to 0 when I change the bounds.

    Complete process is...

    1. store current angle
    2. set the view's angle to 0
    3. set new bounds
    4. set the stored angle