Есть ли способ добавить ограничение между представлением и верхним руководством по компоновке в файле xib?
в iOS 7 Теперь мы можем добавить ограничение между представлением и верхним руководством по макету, которое, я думаю, очень полезно для решения проблемы смещения строки состояния в iOS7(особенно когда в представлении нет панели навигации).
в файле раскадровки я могу легко добавить такие ограничения. Просто удерживайте клавишу управления, а затем перетащите представление в контейнер, он покажет опцию "верхнее пространство для верхнего руководства по компоновке".

но когда я делаю то же самое работа в xib файл, эта опция исчезает.

Итак, есть ли способ добавить такого рода ограничения в xib файлы? Или мне нужно добавить их с кодом?
7 ответов:
вы должны обратиться к следующему примеру, это, безусловно, поможет вам для вашей проблемы. Я получил это от http://developer.apple.com .
[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] ];
вот мое альтернативное решение.
найдите UIView в качестве оси, установите его ограничение верхнего макета фиксированное вертикальное пространство в верхней части контейнера.
Control-перетащите это ограничение макета как IBOutlet, например
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topLayoutConstraint;наконец, просто переопределите метод viewWillLayoutSubviews UIViewController следующим образом
- (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; self.topLayoutConstraint.constant = [self.topLayoutGuide length] + YOUR_TOP_CONSTRSINT; }верхнее ограничение всех других представлений основано на этом сводном представлении, все сделано :)
из iOS 9 вы также можете сделать это более просто с topLayoutGuide в
anchors:
- Swift 3
view.topAnchor.constraint(equalTo: self.topLayoutGuide.bottomAnchor).isActive = true
- ObjC
[controller.view.topAnchor constraintEqualToAnchor:controller.topLayoutGuide.bottomAnchor].active = YES;
до сих пор даже с помощью XCode 6 я не могу выровнять элементы управления в верхнем руководстве по компоновке .xib файлов. Вместо этого, я использую альтернативный способ.
во-первых, в interface builder я все еще выравниваю элементы управления по верхней границе представления viewcontroler.
затем, в методе viewDidLoad, я заменяю некоторые ограничения, чтобы они выровнялись по верхнему руководству макета вместо основного вида:
- (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; }думаю, что это не лучший способ, потому что мы заменяем объекты, которые мы определяем на интерфейсе строитель. Но это может быть альтернативный способ, о котором мы можем думать.
конечно, вы не можете только добавить ограничение между представлением и
top layout guideилиbottom layout guideпрограммно, но также вы можете удалить и ограничение доступа между представлением иtop and bottom layout guideС помощью KVConstraintExtensionsMaster библиотека.// 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 ];
Я думаю, что причина, по которой они не отображаются в XIB, заключается в том, что в этой ситуации нет знаний об иерархии контроллера вида, тогда как в раскадровке IB может сказать, где находятся направляющие из иерархии контроллера вида, в которой находится представление. Т. е. если он содержится в UINavigationController, он может определить, что верхнее руководство по компоновке находится ниже панели инструментов навигации.
ответ Cao Huu Loc с swift 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) } } } }
Comments