当前位置: 首页 > 知识库问答 >
问题:

快速动画计时和自动布局约束会导致不协调的过渡

申颖逸
2023-03-14

目标:应用基于约束的动画,以便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()
        }

        
    }
}

共有1个答案

轩辕煜
2023-03-14

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

@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放置在块内,则会设置动画。按钮标题和标题颜色不可设置动画,因此我将它们从块中删除。

 类似资料:
  • 我在学习教程中的动画自动布局 http://weblog.invasivecode.com/post/42362079291/auto-layout-and-core-animation-auto-layout-was 一切都很顺利。 当我尝试在我的应用程序中使用这个概念,尝试从下到上设置设置屏幕(UIView)的动画时,当设置屏幕只是一个空的UIView时,效果非常好, 但如果我将UILabel

  • 问题内容: 我有一个UITextField我想在点击时扩大它的宽度。我设置了约束,并确保左侧的约束的优先级低于我要尝试在右侧进行动画的优先级。 这是我尝试使用的代码。 这可行,但是似乎只是瞬间发生,似乎没有任何动作。我尝试将其设置为10秒以确保没有遗漏任何东西,但得到的结果相同。 nameInputConstraint是我控制拖动以从IB连接到我的类的约束的名称。 谢谢您的帮助! 问题答案: 您需

  • 下面的函数只是将视图移动到一个新位置。它不显示动画:

  • 我是AutoLayout的新手。我已经知道很多关于这个autoLayout的问题和教程,但是我还没有找到我的解决方案。所以提前感谢您的任何帮助。 我的要求是什么? 我必须制作UIView,它将在按下屏幕底部带有动画的按钮后出现在屏幕上。(如键盘)。我使用autoLayout在xib文件中创建了此UIView。到目前为止,我已经这样做了。 在ViewDidLoad中: 在这个视图中,它包含(滚动视图

  • 许多有关自动布局约束动画的教程建议更新约束的常量属性,然后在动画块中调用。 我的处境有点棘手。我有一个包含3个子视图的视图。此超级视图的高度不是固定的-它是按其子视图的高度之和计算的。在某些情况下,我要求这3个子视图中的一个子视图切换其高度(它在0和30之间变化,即我希望平滑地隐藏和显示它)。代码类似于此: 不幸的是,这并不像我预期的那样有效。我可以看到子视图高度的平滑变化,但在为子视图高度约束设

  • 我有一组AL约束来定位一个子vc,它有两个位置,展开和折叠。 我发现,当我添加折叠约束时,带有常量的上锚到下锚约束,当第一次创建vc时,当我激活它时,似乎有额外的间距。似乎是因为当时没有实际的高度。 当我在viewDidLayoutSubviews中添加约束时,额外的间距消失了,约束行为正常。除了现在在动画中的约束之间切换时,切换到展开约束和约束打断时,无法停用折叠的约束。可能是因为在整个过渡动画