以编程方式更改约束只会影响视图的可见部分

Posted

技术标签:

【中文标题】以编程方式更改约束只会影响视图的可见部分【英文标题】:Changing constraints programmatically only affects visible parts of the view 【发布时间】:2015-07-25 17:34:31 【问题描述】:

我在 Interface Builder 中用两组约束构建了一个带有静态单元格的 TableView。一个用于编辑视图,一个仅用于查看。不仅仅是改变三个文本框的位置。

第一组约束在界面构建器中被激活,第二组被停用(“已安装”未被选中)。

然后,当用户首先单击“编辑”时,旧约束被停用,而其他约束被激活:

@IBOutlet var nonEditableConstraints: [NSLayoutConstraint]!
@IBOutlet var editableConstraints: [NSLayoutConstraint]!

override func setEditing(editing: Bool, animated: Bool) 
        super.setEditing(editing, animated: animated)

        view.layoutIfNeeded()

        if (animated) 
            UIView.animateWithDuration(1.0)  () -> Void in
                self.setControlsEditing(editing)
                self.setContraintsEditing(editing)
                self.view.layoutIfNeeded()
            
         else 
            setControlsEditing(editing)
            setContraintsEditing(editing)
        
    

private func setContraintsEditing(editing: Bool) 
        // we need to make sure to deakcivate constraints before activating new ones
        if (editing) 
            for constraint in nonEditableConstraints 
                constraint.active = false
            

            for constraint in editableConstraints 
                constraint.active = true
            
         else 
            for constraint in editableConstraints 
                constraint.active = false
            

            for constraint in nonEditableConstraints 
                constraint.active = true
            
        
    

这很好用。唯一的问题是,当约束发生变化时,只要三个“宏观营养”字段中的一部分受到约束更改不可见,它们就会保持默认状态(IB 设置的状态)。当 iPhone 处于横向模式时会发生这种情况。几个例子:

这是它在默认模式下的外观(由 IB 设置):

当我在所有三个文本框都可见时按编辑(正确布局):

这是我在向下滚动之前按下编辑时它在横向中的样子(碳水化合物不可见)。当我按完成并再次编辑时,一切都是正确的,因为所有文本框都是可见的:

【问题讨论】:

您是否尝试在受影响的视图上调用setNeedsLayout?此外,您不应该在动画条件之外调用view.layoutIfNeeded(),如果您不制作动画,您应该通过setNeedsLayout 将布局标记为脏,并让后续布局通过处理它。简而言之,您通常只需要为动画(或交互式布局中使用的更高级的离屏布局)调用 layoutIfNeeded 【参考方案1】:

我自己解决了。显然,您应该只更改视图控制器的 viewDidLayoutSubviews() 方法中的约束。我以这种方式更改了代码:

override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews()
    setContraintsEditing(editing)


override func setEditing(editing: Bool, animated: Bool) 
    super.setEditing(editing, animated: animated)

    if (animated) 
        view.layoutIfNeeded()
        UIView.animateWithDuration(1.0)  () -> Void in
            self.setControlsEditing(editing)
            self.view.layoutIfNeeded()
        
     else 
        setControlsEditing(editing)
    

如您所见,setContraintsEditing(bool) 方法现在是从正确的位置调用的,动画块通过 layoutIfNeeded() 间接调用该方法。

【讨论】:

以上是关于以编程方式更改约束只会影响视图的可见部分的主要内容,如果未能解决你的问题,请参考以下文章

无法以编程方式设置列表视图中按钮的可见性

显示/隐藏片段并以编程方式更改可见性属性

出现键盘时以编程方式更新约束

以编程方式创建的 UIButton 不可见

以编程方式修改自动布局约束时视图不更新

UISearchBar 在向下滚动之前不可见