【问题标题】:Maintaining the location of a view when changing its anchor point在更改其锚点时保持视图的位置
【发布时间】:2018-04-06 18:41:10
【问题描述】:

我有一个以编程方式创建并设置了约束的 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)

我尝试在设置 anchorPoint 后只替换它的框架和中心点(另外,我先尝试了框架,然后是中心),但是这些解决方案都没有对应用程序中的视图显示方式产生任何影响:

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

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

【问题讨论】:

    标签: ios swift uilabel nslayoutconstraint cgaffinetransform


    【解决方案1】:

    一种方法:将标签的前导约束保存在一个变量中,然后更改其常量以说明锚点的变化。

    您应该能够按原样运行它。点击按钮为标签设置动画。

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

    【讨论】:

    • 感谢您抽出宝贵的时间!对我来说,它在 viewDidAppear 中不起作用,因为我在那里有另一行代码受到干扰,但是使用变量约束并相对于 anchorPoint 变化进行调整是完全的赢家——我只需要在运行时的不同点运行它我的项目是如何配置的。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 2022-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多