【问题标题】:Swift animation timing and auto layout constraints leads to uncoordinated transitionSwift 动画时序和自动布局约束导致过渡不协调
【发布时间】:2021-05-15 06:29:02
【问题描述】:

目标:应用基于约束的动画,以便 UILabel 改变高度同时保持其顶部锚点约束。

问题:约束和视图适当更新,但似乎存在时间差异 - 高度约束首先更改(好像从零高度开始),而不是保持固定到顶部锚约束。

感谢任何反馈或指导。

.

class ViewController: UIViewController {

    private var button : UIButton = {
       let button = UIButton()
        button.backgroundColor = .red
        button.setTitle("Hello", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.textAlignment = .center
        button.titleLabel?.font = .systemFont(ofSize: 24, weight: .bold)
        button.setTitleColor(.white, for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(self, action: #selector(changeConstraints), for: .touchUpInside)
        return button
    }()
    
    private var label : UILabel = {
       let label = UILabel()
        label.backgroundColor = .blue
        label.text = "This is my label"
        label.font = .systemFont(ofSize: 34, weight: .semibold)
        label.textAlignment = .center
        label.textColor = .white
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    private var animationCount = 0
    
    private var labelHeightConstraint : NSLayoutConstraint = NSLayoutConstraint()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        setupUI()

    }

    func setupUI() {
        
        view.addSubview(button)
        view.addSubview(label)

        // setting initial label height constraint
        labelHeightConstraint =  label.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.6)
        labelHeightConstraint.isActive = true
        
       
        
        NSLayoutConstraint.activate([
        
        
            label.topAnchor.constraint(equalTo: view.topAnchor, constant: 10),
            label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),

            button.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 20),
            button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20),
            button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            button.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
        

        ])
        
    }

    
    @objc func changeConstraints() {
        
        print("changeConstraints method CALLED")
        
        //count for animation state
        animationCount += 1
        
        UIView.animate(withDuration: 2.0) { [unowned self] in
            if animationCount % 2 == 0 {
                labelHeightConstraint.isActive = false
                labelHeightConstraint = label.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.6)
                button.setTitle("GoodBye", for: .normal)
                button.backgroundColor = .purple
                button.setTitleColor(.white, for: .normal)
            } else {
                labelHeightConstraint.isActive = false
                labelHeightConstraint = label.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2)
                button.setTitle("Welcome Back", for: .normal)
                button.backgroundColor = .green
                button.setTitleColor(.black, for: .normal)
            }
            
            labelHeightConstraint.isActive = true
            self.view.layoutIfNeeded()
        }

        
    }
}

【问题讨论】:

  • 也许以trying to animate a constraint in swift 开头(当我不记得该怎么做时,我会这样做)。您应该在开始动画之前修改约束,然后简单地在动画中触发布局传递......显然
  • @MadProgrammer 感谢您的链接,它很有用,但我仍然面临关于顶部锚点断裂以保留高度约束的相同问题。我已经采取了多种不同的方式,但将通过该链接中的不同选项来工作,看看是否有任何产生预期的结果。

标签: swift animation autolayout constraints


【解决方案1】:

你为什么不试试这段代码:

@objc func changeConstraints() {
    print("changeConstraints method CALLED")
    
    //count for animation state
    animationCount += 1
    if animationCount % 2 == 0 {
        labelHeightConstraint = label.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.6)
        button.setTitle("GoodBye", for: .normal)
        button.setTitleColor(.white, for: .normal)
    } else {
        labelHeightConstraint = label.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2)
        button.setTitle("Welcome Back", for: .normal)
        button.setTitleColor(.black, for: .normal)
    }

    UIView.animate(withDuration: 2.0) {
        self.view.layoutIfNeeded()
        self.button.backgroundColor = self.animationCount % 2 == 0 ? .purple : .green
    }   
}

不需要激活和取消激活约束。也不需要分配新的约束,直接修改乘数即可。

在动画块内进行约束更改也不是必需的,如果您将 layoutIfNeeded 放在块内,它将动画。 Button title 和 titleColor 是不可动画的,所以我将它们从块中删除。

【讨论】:

  • labelHeightConstraint.multiplier 是仅获取属性。你不能赋值。
  • 感谢您的努力,但代码 sn-p 没有产生预期的结果(它实际上没有动画)。
猜你喜欢
  • 1970-01-01
  • 2015-04-02
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
相关资源
最近更新 更多