ios 使用constraintEqualToAnchor()时如何在设置后更改自动布局约束?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34391732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:26:24  来源:igfitidea点击:

How to change Auto Layout constraints after they are set when using constraintEqualToAnchor()?

iosswiftuiviewautolayoutnslayoutconstraint

提问by Joe Huang

I try to set up a view with AutoLayout constraints by using constraintEqualToAnchor():

我尝试使用以下方法设置具有 AutoLayout 约束的视图constraintEqualToAnchor()

override func viewDidLoad() {
    super.viewDidLoad()

    let myView = UIView()
    myView.backgroundColor = UIColor.orangeColor()
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)

    myView.leftAnchor.constraintEqualToAnchor(view.leftAnchor).active = true
    myView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true
    myView.topAnchor.constraintEqualToAnchor(view.topAnchor).active = true
    myView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor).active = true

    /******************************************/
    /* I try to change one of the constraints */
    /******************************************/
    myView.leftAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -100).active = true  
}

In the last line of code, I try to change one of the constraints. I thought it would work but it gives some error in the console log

在最后一行代码中,我尝试更改其中一个约束。我认为它会起作用,但它在控制台日志中出现了一些错误

"<NSLayoutConstraint:0x7fb53a5180d0 H:|-(0)-[UIView:0x7fb53a5190b0](LTR)   (Names: '|':UIView:0x7fb53a519240 )>",
"<NSLayoutConstraint:0x7fb53a51f660 H:[UIView:0x7fb53a519240]-(-100)-[UIView:0x7fb53a5190b0](LTR)>",
"<NSLayoutConstraint:0x7fb53a711ee0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7fb53a519240(414)]>"

When using constraintEqualToAnchor()?, what's the right way to change the constraint later after I have set them?

使用时constraintEqualToAnchor()?,在我设置约束后更改约束的正确方法是什么?

回答by vacawama

You need to deactivate the previous constraint when activating a new one so that you don't end up over constraining your view. To do that, store a reference to each of the constraints as a property in your ViewControllerand then set the activeproperty of the old constraint to falsebefore creating and activating the new constraint:

您需要在激活新约束时停用先前的约束,以免最终过度约束您的视图。为此,请将每个约束的引用作为属性存储在您的属性中ViewController,然后在创建和激活新约束之前active将旧约束的属性设置为false

Swift 2.x:

斯威夫特 2.x:

class ViewController: UIViewController {
    var leftConstraint: NSLayoutConstraint?
    var trailingConstraint: NSLayoutConstraint?
    var topConstraint: NSLayoutConstraint?
    var bottomConstraint: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()

        let myView = UIView()
        myView.backgroundColor = UIColor.orangeColor()
        myView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(myView)

        leftConstraint = myView.leftAnchor.constraintEqualToAnchor(view.leftAnchor)
        leftConstraint?.active = true

        trailingConstraint = myView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor)
        trailingConstraint?.active = true

        topConstraint = myView.topAnchor.constraintEqualToAnchor(view.topAnchor)
        topConstraint?.active = true

        bottomConstraint = myView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor)
        bottomConstraint?.active = true

        /******************************************/
        /* I try to change one of the constraints */
        /******************************************/
        leftConstraint?.active = false
        leftConstraint = myView.leftAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -100)
        leftConstraint?.active = true
    }
}


Update for Swift 3syntax:

Swift 3语法更新:

class ViewController: UIViewController {
    var leftConstraint: NSLayoutConstraint?
    var trailingConstraint: NSLayoutConstraint?
    var topConstraint: NSLayoutConstraint?
    var bottomConstraint: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()

        let myView = UIView()
        myView.backgroundColor = UIColor.orange
        myView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(myView)

        leftConstraint = myView.leftAnchor.constraint(equalTo: view.leftAnchor)
        leftConstraint?.isActive = true

        trailingConstraint = myView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        trailingConstraint?.isActive = true

        topConstraint = myView.topAnchor.constraint(equalTo: view.topAnchor)
        topConstraint?.isActive = true

        bottomConstraint = myView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        bottomConstraint?.isActive = true

        /******************************************/
        /* I try to change one of the constraints */
        /******************************************/
        leftConstraint?.isActive = false
        leftConstraint = myView.leftAnchor.constraint(equalTo: view.rightAnchor, constant: -100)
        leftConstraint?.isActive = true
    }
}

回答by Lucas Derraugh

Here is an example declaring a constraint cwhich will be referenced later in time. We set a new constant value and then call layouton the superview.

这是一个声明约束的示例c,稍后将引用该约束。我们设置一个新的常量值,然后调用layout超级视图。

myView.translatesAutoresizingMaskIntoConstraints = false

var constraints: [NSLayoutConstraint] = [
    myView.topAnchor.constraintEqualToAnchor(view.topAnchor),
    myView.leftAnchor.constraintEqualToAnchor(view.leftAnchor),
    myView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor)
]         
let c = myView.rightAnchor.constraintEqualToAnchor(view.rightAnchor)       
constraints.append(c)   

view.addSubview(myView)
NSLayoutConstraint.activateConstraints(constraints)

// Some time later
c.constant = -100
view.setNeedsLayout()

回答by Roman Solodyashkin

// method myView.topAnchor.constraintEqualToAnchor creates new one inactive anchor 
// and not returns exist with equal relationships     

// you can set identifier for any constraint in Interface Builder or code and find & update in code
for ( NSLayoutConstraint *c in [self.view constraintsAffectingLayoutForAxis:UILayoutConstraintAxisHorizontal] )
{
    if ( YES == [c.identifier isEqualToString:@"my.layout-constraint.id"] )
    {
        // Unlike the other properties, the constant can be modified
        // after constraint creation. 
        // Setting the constant on an existing constraint performs much better 
        // than removing the constraint and adding a new one that's exactly like 
        // the old except that it has a different constant.

        c.constant = 123;

        // if needed
        // [self.view setNeedsUpdateConstraints];

        break;
    }
}

回答by Ahmadiah

Here is example with IF statement modifying a StackView and View when a segmented clicked:

以下是 IF 语句在分段单击时修改 StackView 和 View 的示例:

if (sender as AnyObject).selectedSegmentIndex == 0{


        // Shrink the white view and stack view
        heightConstraintView = containerView.heightAnchor.constraint(equalToConstant: 100)
        heightConstraintView?.isActive = true

        heightConstraintStackView = stackView.heightAnchor.constraint(equalToConstant: 100)
        heightConstraintStackView?.isActive = true
    }

    else {


        // Before returning back the white view and stack view DEACTIVATE teh previous constraints
        heightConstraintView?.isActive = false
        heightConstraintStackView?.isActive = false

        // Returning back the white view and stack view to normal size
        heightConstraintView = containerView.heightAnchor.constraint(equalToConstant: 200)
        heightConstraintView?.isActive = true

        heightConstraintStackView = stackView.heightAnchor.constraint(equalToConstant: 200)
            heightConstraintStackView?.isActive = true
    }