Creating Auto Layout constraints to topLayoutGuide and bottomLayoutGuide in code
Solution 1
For a UIButton
that you want to place 20 points below the UIViewController.topLayoutGuide
you create the NSLayoutConstraint
like so:
[NSLayoutConstraint constraintWithItem:self.button
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.topLayoutGuide
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:20.0];
With iOS 9 you can also create the NSLayoutConstraint
this way:
[self.button.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor
constant:20.0];
Solution 2
To supplement @JamieMcDaniel's answer, the Swift + iOS9 version would be:
self.button.topAnchor
.constraintEqualToAnchor( self.topLayoutGuide.bottomAnchor ).active = true
Don't forget the .active = true
part as otherwise the constraint doesn't kick in automatically.
Solution 3
Just an addition to @Jamie McDaniel, in case it's not immediately obvious, you need to add the constraint that he suggests to create:
NSLayoutConstraint *buttonTopConstraint = [NSLayoutConstraint constraintWithItem:self.button
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.topLayoutGuide
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:20.0];
[self.view addConstraint:buttonTopConstraint];
Solution 4
This is a gist I've created, you are supposed to embed all your subviews into a tank view(container view) added into a xib, it removes tank view-superview xib constraints and adds an upper constraints to topLayoutGuide giving an iOS6 look. It could be interesting for what you want to achieve.
//This should be added before the layout of the view
- (void) adaptToTopLayoutGuide {
//Check if we can get the top layoutguide
if (![self respondsToSelector:@selector(topLayoutGuide)]) {
return;
}
//tankView is a contaner view
NSArray * array = [self.tankView referencingConstraintsInSuperviews]; //<--For this method get the Autolayout Demistified Book Sample made by Erica Sadun
[self.view removeConstraints:array];
NSArray * constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topLayoutGuide]-0-[tankView]|" options:0 metrics:nil views:@{@"tankView": self.tankView, @"topLayoutGuide":self.topLayoutGuide}];
[self.view addConstraints:constraintsVertical];
NSArray * constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tankView]|" options:0 metrics:nil views:@{@"tankView": self.tankView}];
[self.view addConstraints:constraintsHorizontal];
}
smileyborg
Updated on July 08, 2022Comments
-
smileyborg almost 2 years
Apple's documentation on creating Auto Layout constraints between a view and one of the layout guides only shows an example using VFL.
Is there any way to create these constraints programmatically without VFL (using
NSLayoutConstraint
's other API or similar)?(Note: I'm specifically asking about doing this in code, not in Interface Builder. And I don't want the calculated
length
of the guide set as a static constant on a constraint, I want a constraint where changes to the layout guide length would automatically cause the constrained view to adjust position.) -
smileyborg over 10 yearsSorry, but this doesn't address my specific question.
-
Andrea over 10 yearsVLF is the way to go with autolayout, I can't find any specific reason for not using it, I've just suggested a piece of code that could help you to point into the right direction.. If you want to think about it.
-
smileyborg over 10 yearsVFL has it's own set of pros and cons. I am personally not a big fan of it, that's why I wrote this Auto Layout category on UIView which solves even more use cases than VFL can. I've even written some pros/cons of all the Auto Layout approaches (including VFL) on the README of that project.
-
Andrea over 10 yearsReally interesting... I've read the readme and I agree with your points, the thing that I'm missing is the Use case, I mean why use normal layout for general purpose layouting, instead of VLF?, performance?or something else?
-
smileyborg over 10 yearsWhat do you mean by "normal layout"?
-
Andrea over 10 yearsI mean create each single constraint programmatically without using VLF, until now I've never found it limiting in general use. I'm just curious why would someone use single constraint instead of VLF, I understand that maybe there are exceptions about sort of particular layouting. Is there a performace reason?
-
smileyborg over 10 yearsTake a look at the what the auto layout code looks like in the example project on GitHub. In my opinion, it's nicer to read & write than VFL (less crazy syntax, more Obj-C like). It's not about performance at all. But it is about compiler checking, easier debugging (knowing exactly what each line is doing), and easier learning curve among other things.
-
smileyborg over 10 years
-
smileyborg over 10 yearsYou're (half?) right. Your code does work, but
NSLayoutAttributeBaseline
is not required to get it to work. If you're pinning to thetopLayoutGuide
,NSLayoutAttributeBottom
works the same (andNSLayoutAttributeTop
should be used when pinning to thebottomLayoutGuide
of course). Anyways...I thought I tried this approach before and it didn't work...guess I screwed something up. -
Ferran Maylinch almost 9 yearsAndrea, it's a shame you got negative points for a correct answer that is even really useful! Both VFL and
constraintWithItem
methods are right, it's just a matter of taste. I prefer VFL whenever possible, I just miss some features like centering. To cut some code I created a really simple Autolayout helper, just in case you find it useful. -
Jamie McDaniel over 8 yearsThanks @smileyborg. I also updated my answer to include the new iOS 9 API.
-
Michael Kessler about 8 yearsI'd suggest to change the vertical constraint(s) from
@"V:|[topLayoutGuide]-0-[tankView]|"
to@"V:[topLayoutGuide][tankView]|"
(removed the relation between the top of the superview and the top layout guide and the-0-
between the top layout guide and tankView)...