在更改视图锚点时保持视图的位置



我有一个以编程方式创建的UILabel,并使用约束进行设置:

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

然后我想把这个标签发展到现场:

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)

但是标签是左对齐的,并且它从中心增长,所以我更改了锚点来修复问题,但这导致标签出现在比应有的更右的位置。(我理解这是因为我现在在视图的左侧而不是中心描述它的位置(

theLabel.layer.anchorPoint = CGPoint(x: 0.0, y: 0.5)
设置锚点后,我尝试

仅替换其框架和中心点(分别,我首先尝试了框架,然后尝试了中心(,但这些解决方案都没有对视图中的显示方式产生任何影响:

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

还有其他建议或解释可以帮助我了解如何在更改视图锚点的同时有效地保留视图的位置吗?谢谢大家!

一种方法:将标签的前导约束保存在变量中,然后更改其常量以考虑 anchorPoint 中的更改。

您应该能够按原样运行。点击按钮以动画显示标签。

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

最新更新