我可以更改NSLayoutConstraint乘数属性?

我在一个超级视图中创build了两个视图,然后在视图之间添加了约束:

_indicatorConstrainWidth = [NSLayoutConstraint constraintWithItem:self.view1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view2 attribute:NSLayoutAttributeWidth multiplier:1.0f constant:0.0f]; [_indicatorConstrainWidth setPriority:UILayoutPriorityDefaultLow]; _indicatorConstrainHeight = [NSLayoutConstraint constraintWithItem:self.view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view2 attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f]; [_indicatorConstrainHeight setPriority:UILayoutPriorityDefaultLow]; [self addConstraint:_indicatorConstrainWidth]; [self addConstraint:_indicatorConstrainHeight]; 

现在我想改变乘数属性与animation,但我不知道如何改变倍数属性。 (我发现在头文件NSLayoutConstraint.h私有财产_coefficient,但它是私人。)

我如何更改多种属性?

我的解决方法是删除旧的约束,并添加一个不同的值multipler新的一个。

如果您只有两组需要应用的乘法器,则可以从iOS8开始添加两组约束,并决定哪些应该在任何时候处于活动状态:

 NSLayoutConstraint *standardConstraint, *zoomedConstraint; // ... // switch between constraints standardConstraint.active = NO; // this line should always be the first line. because you have to deactivate one before activating the other one. or they will conflict. zoomedConstraint.active = YES; [self.view layoutIfNeeded]; // or using [UIView animate ...] 

这里是Swift中的NSLayoutConstraint扩展,使得设置一个新的乘法器非常简单:

 import Foundation import UIKit extension NSLayoutConstraint { func setMultiplier(multiplier:CGFloat) -> NSLayoutConstraint { NSLayoutConstraint.deactivateConstraints([self]) let newConstraint = NSLayoutConstraint( item: firstItem, attribute: firstAttribute, relatedBy: relation, toItem: secondItem, attribute: secondAttribute, multiplier: multiplier, constant: constant) newConstraint.priority = priority newConstraint.shouldBeArchived = self.shouldBeArchived newConstraint.identifier = self.identifier NSLayoutConstraint.activateConstraints([newConstraint]) return newConstraint } } 

在Swift 3.0中

 import Foundation import UIKit extension NSLayoutConstraint { /** Change multiplier constraint - parameter multiplier: CGFloat - returns: NSLayoutConstraint */ func setMultiplier(multiplier:CGFloat) -> NSLayoutConstraint { NSLayoutConstraint.deactivate([self]) let newConstraint = NSLayoutConstraint( item: firstItem, attribute: firstAttribute, relatedBy: relation, toItem: secondItem, attribute: secondAttribute, multiplier: multiplier, constant: constant) newConstraint.priority = priority newConstraint.shouldBeArchived = self.shouldBeArchived newConstraint.identifier = self.identifier NSLayoutConstraint.activate([newConstraint]) return newConstraint } } 

演示用法:

 @IBOutlet weak var myDemoConstraint:NSLayoutConstraint! override func viewDidLoad() { let newMultiplier:CGFloat = 0.80 myDemoConstraint = myDemoConstraint.setMultiplier(newMultiplier) //If later in view lifecycle, you may need to call view.layoutIfNeeded() } 

multiplier属性是只读的。 你必须删除旧的NSLayoutConstraint,并用新的replace它来修改它。

但是,由于您知道要更改乘数,因此在需要更改代码的情况下,您可以自行更改常数。

辅助函数,我用来改变现有的布局约束的乘数 。 它创build并激活一个新的约束,并停用旧约束。

 struct MyConstraint { static func changeMultiplier(_ constraint: NSLayoutConstraint, multiplier: CGFloat) -> NSLayoutConstraint { let newConstraint = NSLayoutConstraint( item: constraint.firstItem, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: constraint.secondItem, attribute: constraint.secondAttribute, multiplier: multiplier, constant: constraint.constant) newConstraint.priority = constraint.priority NSLayoutConstraint.deactivate([constraint]) NSLayoutConstraint.activate([newConstraint]) return newConstraint } } 

使用情况,将乘数变为1.2:

 constraint = MyConstraint.changeMultiplier(constraint, multiplier: 1.2) 

Objective-C版本的Andrew Schreiber回答

创buildNSLayoutConstraint类的类别,并像这样在.h文件中添加方法

  #import <UIKit/UIKit.h> @interface NSLayoutConstraint (Multiplier) -(instancetype)updateMultiplier:(CGFloat)multiplier; @end 

在.m文件中

 #import "NSLayoutConstraint+Multiplier.h" @implementation NSLayoutConstraint (Multiplier) -(instancetype)updateMultiplier:(CGFloat)multiplier { NSLayoutConstraint *newConstraint = [NSLayoutConstraint constraintWithItem:self.firstItem attribute:self.firstAttribute relatedBy:self.relation toItem:self.secondItem attribute:self.secondAttribute multiplier:multiplier constant:self.constant]; [newConstraint setPriority:self.priority]; newConstraint.shouldBeArchived = self.shouldBeArchived; newConstraint.identifier = self.identifier; newConstraint.active = true; [NSLayoutConstraint deactivateConstraints:[NSArray arrayWithObjects:self, nil]]; [NSLayoutConstraint activateConstraints:[NSArray arrayWithObjects:newConstraint, nil]]; //NSLayoutConstraint.activateConstraints([newConstraint]) return newConstraint; } @end 

稍后在ViewController中为你想要更新的约束创build出口。

 @property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint; 

并在下面更新你想要的乘数

 self.topConstraint = [self.topConstraint updateMultiplier:0.9099]; 

你可以改变“常量”属性,而不是用一个小math来实现相同的目标。 假设你的约束的默认乘数是1.0f。 这是Xamarin C#代码,可以很容易地转换为Objective-C

  private void SetMultiplier(nfloat multiplier) { FirstItemWidthConstraint.Constant = -secondItem.Frame.Width * (1.0f - multiplier); } 

可以阅读:

 var multiplier: CGFloat The multiplier applied to the second attribute participating in the constraint. 

在这个文档页面上 。 这并不意味着应该能够修改乘数(因为它是一个variables)?