In iOS 7 können wir jetzt eine Einschränkung zwischen einer Ansicht und der obersten Layoutanleitung hinzufügen. Dies ist meiner Meinung nach sehr nützlich, um das Problem mit dem Versatz der Statusleiste in iOS7 zu lösen (insbesondere, wenn die Ansicht keine Navigationsleiste enthält).
In einer Storyboard-Datei kann ich diese Art von Einschränkungen einfach hinzufügen. Halten Sie einfach die Steuertaste gedrückt und ziehen Sie die Ansicht in den Container. Daraufhin wird die Option "Top Space to Top Layout Guide" angezeigt.
Wenn ich jedoch den gleichen Vorgang in einer xib-Datei ausführe, verschwindet diese Option.
Gibt es eine Möglichkeit, diese Art von Einschränkungen in xib-Dateien hinzuzufügen? Oder muss ich sie mit Code hinzufügen?
Antworten:
Sie sollten sich auf das folgende Beispiel beziehen, dies wird Ihnen definitiv bei Ihrem Problem helfen. Ich habe dies von http://developer.apple.com erhalten .
[button setTranslatesAutoresizingMaskIntoConstraints: NO]; id topGuide = myViewController.topLayoutGuide; NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings (button, topGuide); [myViewController.view addConstraints: [NSLayoutConstraint constraintsWithVisualFormat: @"V:[topGuide]-20-[button]" options: 0 metrics: nil views: viewsDictionary] ];
quelle
Hier ist meine alternative Lösung.
Suchen Sie eine UIView als Drehpunkt, und legen Sie die Einschränkung für das obere Layout auf einen festen vertikalen Abstand zur Oberseite des Containers fest.
Strg-Ziehen Sie diese Layout-Einschränkung als IBOutlet, z
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topLayoutConstraint;
Zum Schluss überschreiben Sie einfach die viewWillLayoutSubviews-Methode von UIViewController wie folgt
- (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; self.topLayoutConstraint.constant = [self.topLayoutGuide length] + YOUR_TOP_CONSTRSINT; }
Alle obersten Einschränkungen der anderen Ansichten basieren auf dieser Pivot-Ansicht, alles erledigt :)
quelle
Ab iOS 9 können Sie dies auch einfacher mit topLayoutGuides tun
anchors
:view.topAnchor.constraint(equalTo: self.topLayoutGuide.bottomAnchor).isActive = true
[controller.view.topAnchor constraintEqualToAnchor:controller.topLayoutGuide.bottomAnchor].active = YES;
quelle
Bis jetzt kann ich selbst mit XCode 6 keine Steuerelemente an der obersten Layoutanleitung für .xib-Dateien ausrichten. Stattdessen benutze ich einen alternativen Weg.
Erstens richte ich im Interface Builder die Steuerelemente immer noch am oberen Rand der Ansicht von viewcontroler aus.
Dann ersetze ich in der viewDidLoad-Methode einige Einschränkungen, damit sie anstelle der Hauptansicht am oberen Layoutleitfaden ausgerichtet werden:
- (void)viewDidLoad { [super viewDidLoad]; NSArray *constraints = self.view.constraints; for (NSLayoutConstraint *constraint in constraints) { if ( (constraint.firstItem == self.view) && (constraint.firstAttribute == NSLayoutAttributeTop) ) { NSLayoutConstraint *newConstraint = [self constraint:constraint replaceFirstItemBy:self.topLayoutGuide attribute:NSLayoutAttributeBottom]; [self.view removeConstraint:constraint]; [self.view addConstraint:newConstraint]; } else if ( (constraint.secondItem == self.view) && (constraint.secondAttribute == NSLayoutAttributeTop) ) { NSLayoutConstraint *newConstraint = [self constraint:constraint replaceSecondItemBy:self.topLayoutGuide attribute:NSLayoutAttributeBottom]; [self.view removeConstraint:constraint]; [self.view addConstraint:newConstraint]; } } } - (NSLayoutConstraint*)constraint:(NSLayoutConstraint*)constraint replaceFirstItemBy:(id)newItem attribute:(NSLayoutAttribute)newAttribute { UILayoutPriority priority = constraint.priority; NSLayoutRelation relation = constraint.relation; id secondItem = constraint.secondItem; NSLayoutAttribute secondAttribute = constraint.secondAttribute; CGFloat multiplier = constraint.multiplier; CGFloat constant = constraint.constant; NSLayoutConstraint *newConstraint = [NSLayoutConstraint constraintWithItem:newItem attribute:newAttribute relatedBy:relation toItem:secondItem attribute:secondAttribute multiplier:multiplier constant:constant]; newConstraint.priority = priority; return newConstraint; } - (NSLayoutConstraint*)constraint:(NSLayoutConstraint*)constraint replaceSecondItemBy:(id)newItem attribute:(NSLayoutAttribute)newAttribute { UILayoutPriority priority = constraint.priority; id firstItem = constraint.firstItem; NSLayoutAttribute firstAttribute = constraint.firstAttribute; NSLayoutRelation relation = constraint.relation; CGFloat multiplier = constraint.multiplier; CGFloat constant = constraint.constant; NSLayoutConstraint *newConstraint = [NSLayoutConstraint constraintWithItem:firstItem attribute:firstAttribute relatedBy:relation toItem:newItem attribute:newAttribute multiplier:multiplier constant:constant]; newConstraint.priority = priority; return newConstraint; }
Denken Sie, dass dies nicht der beste Weg ist, da wir Objekte ersetzen, die wir im Interface Builder definieren. Aber es kann eine alternative Art sein, über die wir nachdenken können.
quelle
Natürlich können Sie nicht nur Einschränkungen zwischen einer Ansicht und der
top layout guide
oderbottom layout guide
programmgesteuert hinzufügen, sondern auchtop and bottom layout guide
mithilfe der KVConstraintExtensionsMaster- Bibliothek Einschränkungen zwischen einer Ansicht und der Ansicht entfernen und darauf zugreifen .// create containerView UIView *containerView = [UIView prepareNewViewForAutoLayout]; [containerView setBackgroundColor:[UIColor brownColor]]; [self.view addSubview:containerView]; // To add Top and Bottom Layout Guide constraint of containerView [self applyTopLayoutGuideConstraintToView:containerView withPadding:0]; [self applyBottomLayoutGuideConstraintToView:containerView withPadding:50]; // To access top Layout Guide Constraint and update it's constant value. NSLayoutConstraint *topLayoutGuideConstraint = [self accessAppliedTopLayoutGuideConstraintFromView:containerView]; topLayoutGuideConstraint.constant = 50; // To access bottom Layout Guide Constraint and update it's constant value with animation NSLayoutConstraint *bottomLayoutGuideConstraint = [self accessAppliedBottomLayoutGuideConstraintFromView:containerView]; bottomLayoutGuideConstraint.constant = 80; [self.view updateModifyConstraintsWithAnimation:NULL]; // call this for animation // To remove Top and Bottom Layout Guide constraint of containerView [self removeAppliedTopLayoutGuideConstraintFromView:containerView]; [self removeAppliedBottomLayoutGuideConstraintFromView:containerView ];
quelle
Ich denke, der Grund, warum sie in der XIB nicht angezeigt werden, ist, dass in dieser Situation keine Kenntnis der View-Controller-Hierarchie vorhanden ist, während IB in einem Storyboard erkennen kann, wo sich die Hilfslinien aus der View-Controller-Hierarchie befinden, in der sich die Ansicht befindet. Dh wenn es in einem UINavigationController enthalten ist, kann es feststellen, dass sich die obere Layoutanleitung unter der Navigationssymbolleiste befindet.
quelle
Cao Huu Locs Antwort mit schneller 4
extension NSLayoutConstraint { func constraintReplacing(firstItemWith newFirstItem: UILayoutSupport, withAttribute newFirstAttribute: NSLayoutAttribute) -> NSLayoutConstraint { return NSLayoutConstraint(item: newFirstItem, attribute: newFirstAttribute, relatedBy: relation, toItem: secondItem, attribute: secondAttribute, multiplier: multiplier, constant: constant) } func constraintReplacing(secondItemWith newSecondItem: UILayoutSupport, withAttribute newSecondAttribute: NSLayoutAttribute) -> NSLayoutConstraint { return NSLayoutConstraint(item: firstItem as Any, attribute: firstAttribute, relatedBy: relation, toItem: newSecondItem, attribute: newSecondAttribute, multiplier: multiplier, constant: constant) } } class YourViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() for constraint in view.constraints { if constraint.firstItem === view && constraint.firstAttribute == .top { let newConstraint = constraint.constraintReplacing(firstItemWith: topLayoutGuide, withAttribute: .bottom) view.removeConstraint(constraint) view.addConstraint(newConstraint) } if constraint.secondItem === view && constraint.secondAttribute == .top { let newConstraint = constraint.constraintReplacing(secondItemWith: topLayoutGuide, withAttribute: .bottom) view.removeConstraint(constraint) view.addConstraint(newConstraint) } } } }
quelle