【问题标题】:How to programmatically disable constraint when animating动画时如何以编程方式禁用约束
【发布时间】:2019-01-18 18:54:00
【问题描述】:

我有一个固定宽度固定在左侧的视图。我希望这个视图通过将其锚定到右侧(从而移除左锚)来设置动画(从左到右移动)。我该怎么做呢?

我尝试设置优先级,但我不确定语法。我也尝试禁用约束,但没有奏效。

fileprivate func sparkle() {
    let sparkleView = UIView()
    sparkleView.backgroundColor = UIColor.yellow
    sparkleView.alpha = 0.5
    addSubview(sparkleView)
    sparkleView.translatesAutoresizingMaskIntoConstraints = false
    sparkleView.topAnchor.constraint(equalTo: topAnchor).isActive = true
    sparkleView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
    sparkleView.widthAnchor.constraint(equalToConstant: frame.width / 5).isActive = true
    sparkleView.leftAnchor.constraint(equalTo: leftAnchor).priority = UILayoutPriorityDefaultLow // Doesn't work
    sparkleView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
    layoutIfNeeded()
    sparkleView.leftAnchor.constraint(equalTo: leftAnchor).isActive = false // Doesn't work
    sparkleView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
    UIView.animate(withDuration: 2, animations: {
        self.layoutIfNeeded()
    }) { (_) in
        sparkleView.removeFromSuperview()
    }
}

目前,由于我们分配了左右锚点,因此宽度限制被打破。

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x6000020b8eb0 UIView:0x7fc846d551d0.width == 15.35   (active)>

-- 编辑--

我已经尝试创建一个实例变量来保存约束。

let leftCons = sparkleView.leftAnchor.constraint(equalTo: leftAnchor)
leftCons.isActive = true

然后我尝试修改优先级

leftCons.priority = UILayoutPriorityDefaultLow

但是,这会导致错误

'Mutating a priority from required to not on an installed constraint (or vice-versa) is not supported.  You passed priority 250 and the existing priority was 1000.'

相反,我只需将其设置为非活动状态(来自答案)

leftCons.active = false

-- 如果有兴趣,请更正代码..--

fileprivate func sparkle() {
    let sparkleView = UIView()
    sparkleView.backgroundColor = UIColor.yellow
    sparkleView.alpha = 0.5
    addSubview(sparkleView)
    sparkleView.translatesAutoresizingMaskIntoConstraints = false
    sparkleView.topAnchor.constraint(equalTo: topAnchor).isActive = true
    sparkleView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
    sparkleView.widthAnchor.constraint(equalToConstant: frame.width / 5).isActive = true
    let leftCons = sparkleView.leftAnchor.constraint(equalTo: leftAnchor)
    leftCons.isActive = true
    layoutIfNeeded()
    leftCons.isActive = false
    sparkleView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
    UIView.animate(withDuration: 0.5, animations: {
        self.layoutIfNeeded()
    }) { (_) in
        sparkleView.removeFromSuperview()
    }
}

【问题讨论】:

    标签: swift autolayout nslayoutconstraint


    【解决方案1】:

    你需要创建一个变量

    var leftCon:NSLayoutConstraint!
    

    然后改变它,你的问题是每一行都创建一个新的约束

    sparkleView.widthAnchor.constraint(equalToConstant: frame.width / 5).isActive = true
    sparkleView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
    sparkleView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
    

    注意:以上 3 个约束会产生冲突,因为不能同时将视图固定在左右两侧,而宽度约束正是您看到冲突中断的原因 => NSLayoutConstraint:0x6000020b8eb0 UIView:0x7fc846d551d0.width == 15.35(活动)

    不管活动的分配,所以那些

    sparkleView.leftAnchor.constraint(equalTo: leftAnchor).priority = UILayoutPriorityDefaultLow // Doesn't work 
    sparkleView.leftAnchor.constraint(equalTo: leftAnchor).isActive = false // Doesn't work
    

    在运行中并且不改变创建的约束,所以是

    leftCon = sparkleView.leftAnchor.constraint(equalTo: leftAnchor)
    leftCon.isActive = true
    

    关于这次崩溃

    '不支持在已安装的约束上将优先级从需要更改为不设置(反之亦然)

    激活前需要设置优先级

    leftCon.priority = UILayoutPriorityDefaultLow
    leftCon.isActive = true
    

    【讨论】:

    • 是的,这行得通。旁注——你可以在这里使用 let ,因为我们从不改变它。
    • 是的,如果你直接在 1 行中创建它,那么 let 是合适的,上面我的意思是如果它被声明为实例变量
    • 啊,感谢您澄清优先级崩溃!这绝对是有用的信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 2011-03-17
    相关资源
    最近更新 更多