I'm trying to rotate a uiview on top of another view using constraints. Here is what I implemented
mediaContainer.addSubview(overlayView)
keepBottomLeft()
overlayView.layoutIfNeeded()
func keepBottomLeft(overlayView: UIView) {
NSLayoutConstraint(item: overlayView, attribute:.width, relatedBy:.equal,toItem: mediaContainer, attribute:.width, multiplier: 0.8, constant: 0).isActive = true
NSLayoutConstraint(item: overlayView, attribute:.leading, relatedBy:.equal, toItem: mediaContainer, attribute:.leading, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: overlayView, attribute:.height, relatedBy:.equal,toItem: nil, attribute:.notAnAttribute, multiplier: 1.0, constant: 26).isActive = true
NSLayoutConstraint(item: overlayView, attribute:.bottom, relatedBy:.equal, toItem: mediaContainer, attribute:.bottom, multiplier: 1, constant: 0).isActive = true
overlayView.transform = CGAffineTransform(rotationAngle: CGFloat(-M_PI_2))
}
Will it be necessary to use an anchor point? This is what I'm trying to achieve?
What I get is
Can someone point me in the right direction?
Your anchor point is at the yellow view's center; the default. Either you want to move it to the bottom left with layer.anchorPoint = CGPoint(x: 0, y:1) [Note the anchor is in unit coordinates form 0 to 1, not in points]. You will still need an extra translate of x = height.
Alternatively you can concatenate your transforms and move your center to the point you want to rotate about, perform the rotation, and then reverse your translation (this is actually the typical way to do it with 3d transforms).
UPDATE: Here is a playground. Note that you concatenate the matrices in the reverse order that you want the transforms to be applied. I have an animation in here so you can decompose the transforms and see what each one does:
Move the view over by half of its current width and down so its at the bottom of the superview.
import PlaygroundSupport
import UIKit
class V: UIViewController {
var overlayView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
overlayView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(overlayView)
overlayView.backgroundColor = .yellow
overlayView.heightAnchor.constraint(equalToConstant: 26).isActive = true
overlayView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8).isActive = true
overlayView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
overlayView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
}
override func viewDidAppear(_ animated: Bool) {
UIView.animate(withDuration: 1) {
let center = self.overlayView.center
let size = self.overlayView.bounds.size
self.overlayView.transform =
CGAffineTransform(translationX: self.view.bounds.size.height - size.width / 2, y: -size.height/2)
.concatenating(CGAffineTransform(rotationAngle: CGFloat.pi/2)
.concatenating(CGAffineTransform(translationX: -center.x, y: -center.y)))
}
}
}
let v = V()
v.view.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
PlaygroundPage.current.liveView = v