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