164

1 つのスーパービューに 2 つのビューを作成し、ビュー間に制約を追加しました。

_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];

マルチプライヤー プロパティをアニメーションで変更したいのですが、マルチプライヤー プロパティを変更する方法がわかりません。(ヘッダー ファイル NSLayoutConstraint.h のプライベート プロパティに _coefficient が見つかりましたが、プライベートです。)

multipler プロパティを変更するにはどうすればよいですか?

私の回避策は、古い制約を削除し、 の値が異なる新しい制約を追加することですmultipler

4

16 に答える 16

189

これは、新しい乗数の設定を非常に簡単にする Swift の NSLayoutConstraint 拡張です。

Swift 3.0 以降では

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() 
}
于 2015-10-07T22:06:07.160 に答える
128

適用する必要がある乗数のセットが 2 つしかない場合、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 5.0 バージョン

var standardConstraint: NSLayoutConstraint!
var zoomedConstraint: NSLayoutConstraint!

// ...

// switch between constraints
standardConstraint.isActive = false // this line should always be the first line. because you have to deactivate one before activating the other one. or they will conflict.
zoomedConstraint.isActive = true
self.view.layoutIfNeeded() // or using UIView.animate
于 2015-01-08T00:16:55.400 に答える
58

プロパティはmultiplier読み取り専用です。古い NSLayoutConstraint を削除し、新しいものに置き換えて変更する必要があります。

ただし、乗数を変更したいことがわかっているので、変更が必要な場合は自分で乗算することで定数を変更できます。これは多くの場合、コードが少なくて済みます。

于 2013-10-25T15:27:56.750 に答える
52

既存のレイアウト制約の乗数を変更するために使用するヘルパー関数。新しい制約を作成してアクティブにし、古い制約を非アクティブにします。

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)
于 2015-09-30T06:57:09.613 に答える
14

代わりに「定数」プロパティを変更して、少し計算して同じ目標を達成できます。制約の既定の乗数が 1.0f であるとします。これは、objective-c に簡単に変換できる Xamarin C# コードです。

private void SetMultiplier(nfloat multiplier)
{
    FirstItemWidthConstraint.Constant = -secondItem.Frame.Width * (1.0f - multiplier);
}
于 2017-02-21T20:30:15.207 に答える
5

上記のコードはどれも機能しませんでしたので、自分のコードを変更しようとした後、このコード このコードはXcode 10およびswift 4.2で機能しています

import UIKit
extension NSLayoutConstraint {
/**
 Change multiplier constraint

 - parameter multiplier: CGFloat
 - returns: NSLayoutConstraintfor 
*/i
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() 
 }
于 2019-03-17T08:23:45.767 に答える
2

スイフト 5+

Evgenii's answerに基づいて、 multiplierthroughを変更するエレガントな方法を次に示しますextension

extension NSLayoutConstraint {
    func change(multiplier: CGFloat) {
        let newConstraint = NSLayoutConstraint(item: firstItem,
                                               attribute: firstAttribute,
                                               relatedBy: relation,
                                               toItem: secondItem,
                                               attribute: secondAttribute,
                                               multiplier: multiplier,
                                               constant: constant)

        newConstraint.priority = self.priority

        NSLayoutConstraint.deactivate([self])
        NSLayoutConstraint.activate([newConstraint])
    }
}

そして使用法:

myConstraint.change(multiplier: 0.6)
于 2021-11-21T21:50:15.903 に答える
-2

読むことができます:

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

このドキュメントページで。それは、乗数を変更できるべきだということではありませんか (それは var であるため)。

于 2017-10-11T07:26:59.020 に答える