NSLayoutConstraint между панелью навигации и представлением ViewControllers

Можем ли мы добавить NSLayoutConstraint между self.navigationcontroller.navigationbar и вид внутри self.view, Здесь я UIViewController экземпляр и _textField это подвид self.view

Мне нужно, чтобы пользовательский интерфейс выглядел одинаково независимо от того, navigationBar является полупрозрачным или нет.

Я попробовал следующее. Но это не работает.

NSLayoutConstraint* cn = [NSLayoutConstraint constraintWithItem:_textField
                                                      attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                         toItem:self.navigationController.navigationBar attribute:NSLayoutAttributeBottom
                                                     multiplier:1.0 constant:20];
[self.navigationcontroller.view addConstraint:cn];

3 ответа

Да, вы можете добавить ограничение между панелью навигации и представлением. Ваш контроллер корневого представления, добавленный к контроллеру навигации, содержит topLayoutGuide. так что настройте свой код так:

NSLayoutConstraint* cn = [NSLayoutConstraint constraintWithItem:_textField
                                                      attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                         toItem:self.rootViewController.topLayoutGuide attribute:NSLayoutAttributeBottom
                                                     multiplier:1.0 constant:20];
[self.rootViewController.view addConstraint:cn];

обратите внимание, что я вообще не ссылаюсь на контроллер навигации, кроме rootViewController контроллера навигации.

Также вы можете использовать bottomLayoutGuide, чтобы пройти выше TabBar таким же образом. (однако, если вам нужно сделать это, вы столкнетесь с ошибкой в ​​iOS-фреймворках с патчем обхода здесь: UIViews заканчиваются под панелью вкладок)

Проверьте topLayoutGuide собственность на UIViewController.

В документе Apple есть пример UIViewController, который выглядит следующим образом...

topLayoutGuide
Indicates the highest vertical extent for your onscreen content, for use with Auto Layout constraints. (read-only)

@property(nonatomic, readonly, retain) id<UILayoutSupport> topLayoutGuide

А потом...

В качестве примера того, как программно использовать это свойство с автоматическим макетом, скажем, вы хотите расположить элемент управления таким образом, чтобы его верхний край находился на 20 точек ниже верхнего руководства по макету. Этот сценарий применяется к любому из сценариев, перечисленных выше. Используйте код, подобный следующему:

[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]
self.view layoutSubviews; // You must call this method here or the system raises an exception
];

Добавьте ограничение между вершиной textField и вершиной родительского представления. Константа для ограничения может быть установлена ​​на высоту строки состояния + высота панели навигации.

Очевидно, что следующий фрагмент кода будет работать только в том случае, если и строка состояния, и панель навигации полупрозрачны, а контроллер представления требует полноэкранного макета. Вы можете легко проверить прозрачность и соответственно откорректировать при необходимости.

Если вы используете конструктор интерфейса, вы также можете создать IBOutlet для существующего ограничения и просто установить его константу, а не создавать новое ограничение.

// Obtain the view rect of the status bar frame in either portrait or landscape
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
CGRect statusBarWindowRect = [self.view.window convertRect:statusBarFrame fromWindow: nil];
CGRect statusBarViewRect = [self.view convertRect:statusBarWindowRect fromView: nil];

// Add Status Bar and Navigation Bar heights together
CGFloat height = self.navigationController.navigationBar.frame.size.height +
statusBarViewRect.size.height;

// Create & Add Constraint
NSLayoutConstraint *constraint =
[NSLayoutConstraint constraintWithItem:self.fieldLabel
                             attribute:NSLayoutAttributeTop
                             relatedBy:0
                                toItem:self.view
                             attribute:NSLayoutAttributeTop
                            multiplier:1
                              constant:height];

[self.view addConstraint:constraint];
Другие вопросы по тегам