2014-12-23 5 views
28

Ich habe einen UITableViewController, der keine Abschnitte anzeigt, wenn nichts angezeigt werden soll. Ich habe ein Etikett zeigen den Benutzer hinzugefügt, dass es nichts mit diesem Code angezeigt ist:Programmgesteuert Add CenterX/CenterY Constraints

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

Aber jetzt, ich will es horizontal und vertikal zentriert werden.

enter image description here

Ich habe versucht, den folgenden Code die Einschränkungen hinzufügen, aber die App-Abstürze mit Fehlern: Normalerweise würde ich die beiden Optionen markiert (plus diejenigen für Höhe und Breite) in der Abbildung wählen

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) 

Fehler:

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 

das Etikett sollte immer horizontal und vertikal zentriert, da die Anwendung unterstützt Dreh das Gerät.

Was mache ich falsch? Wie füge ich diese Einschränkungen erfolgreich hinzu?

Danke!

+2

Ich erstelle dies in VIEWDIDLOAD. –

+2

Ich sehe die Zeile nicht, in der Sie das Label als Unteransicht zu einer anderen Ansicht hinzufügen. Es ist wichtig, dass Sie das tun, bevor Sie Einschränkungen hinzufügen. –

+0

Ich bin: Label = UILabel (Frame: CGRectMake (20, 20, 250, 100)) label.text = "Nichts zu zeigen" self.tableView.addSubview (Label) –

Antwort

50

Update für Swift 3/Swift 4:

Ab iOS 8, können und sollten Sie Ihre Einschränkungen aktivieren, indem ihre isActive Eigenschaft auf true Einstellung. Dadurch können sich die Abhängigkeiten zu den richtigen Ansichten hinzufügen. Sie können mehrere Einschränkungen aktivieren, indem ein Array vorbei an den Zwängen 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]) 

bessere Lösung enthält:

Da diese Frage wurde ursprünglich beantwortet, Layout Anker eingeführt wurden so dass es viel einfacher, das schaffen Einschränkungen. In diesem Beispiel erstelle ich die Zwänge und sofort aktivieren sie:

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 

Hinweis: Immer dein Subviews der Ansicht Hierarchie fügen vor das Erstellen und die Einschränkungen zu aktivieren.


Ursprüngliche Antwort:

Die Einschränkungen Bezug auf self.tableView machen. Da Sie das Label als Subview self.tableView hinzufügen, müssen die Einschränkungen auf den „gemeinsamen Vorfahren“ hinzugefügt werden:

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

Als @mustafa und @kcstricks in den Kommentaren darauf hingewiesen, müssen Sie Set label.translatesAutoresizingMaskIntoConstraints zu false. Wenn Sie dies tun, müssen Sie auch die width und height der Beschriftung mit Einschränkungen angeben, da der Rahmen nicht mehr verwendet wird. Schließlich sollten Sie auch textAlignment auf .Center setzen, damit Ihr Text in Ihrem Etikett zentriert ist.

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) 
+0

Ausgezeichnet. Vielen Dank. –

8

Programmgesteuert können Sie dies tun, indem Sie die folgenden Einschränkungen hinzufügen.

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]; 
+0

Bitte tauschen constraintVertical mit constraintHorizontal - es ist verwirrend – AlexeyVMP

24

für Swift 3 Aktualisiert

Zentrum in Behälter

enter image description here

Der folgende Code macht das Gleiche wie im Interface Builder Zentrierung.

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 
    // ... 
} 

Methode 1: Anchor Art

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

Methode 2: NSLayoutConstraint Art

NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0).active = true 
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0).active = true 

Hinweise

  • Anchor Style ist die bevorzugte Methode gegenüber NSLayoutConstraint Style, allerdings ist es nur für iOS 9 verfügbar. Wenn Sie also iOS 8 unterstützen, sollten Sie immer noch NSLayoutConstraint Style verwenden.
  • Sie müssen auch Längen- und Breitenbeschränkungen hinzufügen.
  • Meine vollständige Antwort ist here.
1

Wenn Sie nicht über diese Frage kümmern sich speziell um eine Tableview zu sein, und Sie würden nur eine Ansicht wie oben zum Zentrum hier von einer anderen Ansicht ist, es zu tun:

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) 
5

Die ObjectiveC Äquivalent ist:

myView.translatesAutoresizingMaskIntoConstraints = NO; 

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

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

beste für mich, Danke –