I have a UILabel created programmatically and set with constraints:
NSLayoutConstraint.activate([
theLabel.topAnchor.constraint(equalTo: otherView.topAnchor),
theLabel.leadingAnchor.constraint(equalTo: otherView.trailingAnchor, constant: otherView.frame.width/2),
theLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5),
theLabel.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2),
])
I then wanted to grow the label onto the scene:
theLabel.transform = CGAffineTransform(scaleX: 0.0001, y: 0.0001)
theLabel.isHidden = false
UIView.animate(withDuration: 0.8, delay: 0.0, options: UIViewAnimationOptions(), animations: {
self.theLabel.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) //or CGAffineTransform.identity
}, completion: nil)
But the label is left aligned, and it grows from the center, so I changed the anchor point to fix things, but that resulted in the label appearing further to the right than it should be. (I understand this is because I am now describing its position by the left side of the view and no longer by the center)
theLabel.layer.anchorPoint = CGPoint(x: 0.0, y: 0.5)
I tried to just replace its frame and its center point after setting the anchorPoint (separately, I tried first the frame, then the center) but neither of these solutions made any difference to how the view displayed in app:
let oldFrame = theLabel.frame
theLabel.layer.anchorPoint = CGPoint(x: 0.0, y: 0.5)
theLabel.frame = oldFrame
let oldCenter = theLabel.center
theLabel.layer.anchorPoint = CGPoint(x: 0.0, y: 0.5)
theLabel.center = oldCenter
Any other suggestions or explanations to help me understand how I can effectively preserve the location of the view while changing its anchor point? Thanks all!
One approach: save the label's leading constraint in a variable, and then change its constant to account for the change in anchorPoint.
You should be able to run this as-is. Tap the button to animate the label.
class LabelTransformViewController: UIViewController {
let btn: UIButton = {
let b = UIButton()
b.translatesAutoresizingMaskIntoConstraints = false
b.setTitle("Tap Me", for: .normal)
b.backgroundColor = .red
return b
}()
let theLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = UIColor.cyan
v.text = "This is a label"
return v
}()
let otherView: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = UIColor.yellow
return v
}()
var leadingConstraint = NSLayoutConstraint()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: 1.0, green: 0.85, blue: 0.5, alpha: 1.0)
view.addSubview(btn)
btn.addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)
btn.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
btn.topAnchor.constraint(equalTo: view.topAnchor, constant: 20.0).isActive = true
view.addSubview(otherView)
NSLayoutConstraint.activate([
otherView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100.0),
otherView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20.0),
otherView.widthAnchor.constraint(equalToConstant: 30.0),
otherView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2),
])
view.addSubview(theLabel)
NSLayoutConstraint.activate([
theLabel.topAnchor.constraint(equalTo: otherView.topAnchor),
theLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5),
theLabel.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2),
])
leadingConstraint = theLabel.leadingAnchor.constraint(equalTo: otherView.trailingAnchor, constant: otherView.frame.width/2)
leadingConstraint.isActive = true
// presumably, you would start with theLabel hidden
// but we're leaving it visible so we can see its original size and position
// theLabel.isHidden = true
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// move the anchorPoint from the label frame's center (the default)
// to the left edge, vertical center
theLabel.layer.anchorPoint = CGPoint(x: 0.0, y: 0.5)
// adjust the label's leading constraint by 1/2 of its width
// to account for the anchorPoint change
// need this in viewDidAppear so the frame is already set
leadingConstraint.constant -= (theLabel.frame.size.width * 0.5)
}
@objc func didTap(_ sender: Any?) -> Void {
theLabel.transform = CGAffineTransform(scaleX: 0.0001, y: 0.0001)
theLabel.isHidden = false
UIView.animate(withDuration: 0.8, delay: 0.0, options: UIViewAnimationOptions(), animations: {
self.theLabel.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) //or CGAffineTransform.identity
}, completion: nil)
}
}