プログラムでCenterX / CenterY制約を追加する


84

表示するものがない場合、セクションを表示しないUITableViewControllerがあります。このコードで表示するものがないことをユーザーに示すラベルを追加しました。

label = UILabel(frame: CGRectMake(20, 20, 250, 100))
label.text = "Nothing to show"
self.tableView.addSubview(label)

しかし今、私はそれを水平方向と垂直方向の中央に配置したいと思います。通常、スクリーンショットで強調表示されている2つのオプション(および高さと幅のオプション)を選択します。

ここに画像の説明を入力してください

次のコードを試して制約を追加しようとしましたが、アプリがエラーでクラッシュします。

label = UILabel(frame: CGRectMake(20, 20, 250, 100))
label.text = "Nothing to show"

let xConstraint = NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterX, multiplier: 1, constant: 0)
let yConstraint = NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterY, multiplier: 1, constant: 0)

label.addConstraint(xConstraint)
label.addConstraint(yConstraint)

エラー:

When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2014-12-23 08:17:36.755 [982:227877] *** Assertion failure in -[UILabel _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:], /SourceCache/UIKit/UIKit-3318.16.21/NSLayoutConstraint_UIKitAdditions.m:560

アプリはデバイスの回転をサポートしているため、ラベルは常に水平方向と垂直方向の中央に配置する必要があります。

私は何が間違っているのですか?これらの制約を正常に追加するにはどうすればよいですか?

ありがとう!


2
私はこれをVIEWDIDLOADで作成しています。
マリオAグズマン2014

2
ラベルをサブビューとして他のビューに追加する行が表示されません。制約を追加する前にそれを行うことが重要です。
Scott Berrevoets 2014

私は:label = UILabel(frame:CGRectMake(20、20、250、100))label.text = "Nothing to show" self.tableView.addSubview(label)
マリオAグズマン

回答:


163

Swift 3 / Swift4のアップデート:

iOS 8以降、isActiveプロパティをに設定することで制約をアクティブ化できますtrue。これにより、制約が適切なビューに追加されます。制約を含む配列をに渡すことにより、一度に複数の制約をアクティブ化できます。NSLayoutConstraint.activate()

let label = UILabel(frame: CGRect.zero)
label.text = "Nothing to show"
label.textAlignment = .center
label.backgroundColor = .red  // Set background color to see if label is centered
label.translatesAutoresizingMaskIntoConstraints = false
self.tableView.addSubview(label)

let widthConstraint = NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal,
                                         toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 250)

let heightConstraint = NSLayoutConstraint(item: label, attribute: .height, relatedBy: .equal,
                                          toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 100)

let xConstraint = NSLayoutConstraint(item: label, attribute: .centerX, relatedBy: .equal, toItem: self.tableView, attribute: .centerX, multiplier: 1, constant: 0)

let yConstraint = NSLayoutConstraint(item: label, attribute: .centerY, relatedBy: .equal, toItem: self.tableView, attribute: .centerY, multiplier: 1, constant: 0)

NSLayoutConstraint.activate([widthConstraint, heightConstraint, xConstraint, yConstraint])

より良い解決策:

この質問は元々回答されていたため、制約の作成をはるかに簡単にするレイアウトアンカーが導入されました。この例では、制約を作成し、すぐにアクティブにします。

label.widthAnchor.constraint(equalToConstant: 250).isActive = true
label.heightAnchor.constraint(equalToConstant: 100).isActive = true
label.centerXAnchor.constraint(equalTo: self.tableView.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: self.tableView.centerYAnchor).isActive = true

または同じ使用NSLayoutConstraint.activate()

NSLayoutConstraint.activate([
    label.widthAnchor.constraint(equalToConstant: 250),
    label.heightAnchor.constraint(equalToConstant: 100),
    label.centerXAnchor.constraint(equalTo: self.tableView.centerXAnchor),
    label.centerYAnchor.constraint(equalTo: self.tableView.centerYAnchor)
])

注:制約を作成してアクティブ化するに、必ずサブビューをビュー階層追加してください。


元の回答:

制約はを参照しself.tableViewます。のサブビューとしてラベルを追加しているのでself.tableView、制約を「共通の祖先」に追加する必要があります。

   self.tableView.addConstraint(xConstraint)
   self.tableView.addConstraint(yConstraint)

@mustafaと@kcstricksがコメントで指摘しているように、に設定label.translatesAutoresizingMaskIntoConstraintsする必要があります false。これを行うと、あなたも指定する必要がありますwidthheight、もはやフレームが使用されていないため、制約付きラベルのを。最後に、テキストがラベルの中央に配置さtextAlignmentれる.Centerようにをに設定する必要もあります。

    var  label = UILabel(frame: CGRectZero)
    label.text = "Nothing to show"
    label.textAlignment = .Center
    label.backgroundColor = UIColor.redColor()  // Set background color to see if label is centered
    label.translatesAutoresizingMaskIntoConstraints = false
    self.tableView.addSubview(label)

    let widthConstraint = NSLayoutConstraint(item: label, attribute: .Width, relatedBy: .Equal,
        toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 250)
    label.addConstraint(widthConstraint)

    let heightConstraint = NSLayoutConstraint(item: label, attribute: .Height, relatedBy: .Equal,
        toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 100)
    label.addConstraint(heightConstraint)

    let xConstraint = NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterX, multiplier: 1, constant: 0)

    let yConstraint = NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterY, multiplier: 1, constant: 0)

    self.tableView.addConstraint(xConstraint)
    self.tableView.addConstraint(yConstraint)

優秀な。ありがとうございました。
App Dev Guy

1
アンカーは私のために働いた-私はあなたの努力に感謝します!
FullMetalFist 2018年

37

コンテナの中心

ここに画像の説明を入力してください

以下のコードは、InterfaceBuilderのセンタリングと同じことを行います。

override func viewDidLoad() {
    super.viewDidLoad()

    // set up the view
    let myView = UIView()
    myView.backgroundColor = UIColor.blue
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)

    // Add code for one of the constraint methods below
    // ...
}

方法1:アンカースタイル

myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

方法2:NSLayoutConstraintスタイル

NSLayoutConstraint(item: myView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0).isActive = true

ノート

  • アンカースタイルはNSLayoutConstraintStyleよりも推奨される方法ですが、iOS 9からのみ使用できるため、iOS 8をサポートしている場合は、引き続きNSLayoutConstraintStyleを使用する必要があります。
  • また、長さと幅の制​​約を追加する必要があります。
  • 私の完全な答えはここにあります

10

ObjectiveCに相当するものは次のとおりです。

    myView.translatesAutoresizingMaskIntoConstraints = NO;

    [[myView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor] setActive:YES];

    [[myView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor] setActive:YES];

私にとって最高のもの、ありがとう
Fadi Abuzant 2017

8

プログラムで、次の制約を追加することでそれを行うことができます。

NSLayoutConstraint *constraintHorizontal = [NSLayoutConstraint constraintWithItem:self  
                                                                      attribute:NSLayoutAttributeCenterX 
                                                                      relatedBy:NSLayoutRelationEqual 
                                                                         toItem:self.superview 
                                                                      attribute:attribute 
                                                                     multiplier:1.0f 
                                                                       constant:0.0f];

NSLayoutConstraint *constraintVertical = [NSLayoutConstraint constraintWithItem:self
                                                                        attribute:NSLayoutAttributeCenterY 
                                                                        relatedBy:NSLayoutRelationEqual
                                                                           toItem:self.superview 
                                                                        attribute:attribute 
                                                                       multiplier:1.0f
                                                                         constant:0.0f];

制約
Verticalを

5

Swift 5では、次のようになります。

label.translatesAutoresizingMaskIntoConstraints = false
label.centerXAnchor.constraint(equalTo: vc.view.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: vc.view.centerYAnchor).isActive = true

1

この質問が特にテーブルビューに関するものであることを気にせず、あるビューを別のビューの上に中央揃えにしたい場合は、次のようにします。

    let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: parentView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
    parentView.addConstraint(horizontalConstraint)

    let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: parentView, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)
    parentView.addConstraint(verticalConstraint)

1

私にとっての解決策は、を作成しUILabel、それをUIButtonサブビューとしてに追加することでした。最後に、ボタンの中央に配置するための制約を追加しました。

UILabel * myTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 75, 75)];
myTextLabel.text = @"Some Text";
myTextLabel.translatesAutoresizingMaskIntoConstraints = false;

[myButton addSubView:myTextLabel];

// Add Constraints
[[myTextLabel centerYAnchor] constraintEqualToAnchor:myButton.centerYAnchor].active = true;
[[myTextLabel centerXAnchor] constraintEqualToAnchor:myButton.centerXAnchor].active = true; 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.