scrollView: how to create a pure auto layout scrollview with paging? - ios

Can someone tell me what I did wrong here...
- pin the UIScrollView to its container view
- pin all subviews onto UIScrollView
After reading the Apple TechNote about it, I tried both hybrid method and pure auto layout method. The hybrid method using NIB works awful with paging, it looks like a big picture in a scrollview, rather than paged.
I then created the pure auto layout version in code, UIScrollView as subview of a UIView. This time the view stuck, and the UIImage is gigantic, like its full size:
//scroll view
if (self.scrollView == nil)
{
self.scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.scrollView setClipsToBounds:NO];
[self.scrollView setPagingEnabled:YES];
[self addSubview: self.scrollView];
[self addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrollView(300)]|"
options:0 metrics:nil
views:#{#"scrollView":self.scrollView}]];
[self addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrollView(300)]|"
options:0 metrics:nil
views:#{#"scrollView":self.scrollView}]];
-(void) createContentView
{
for (int i=0; i<self.pageImages.count; i++) {
UILabel* topLabel = [[UILabel alloc] init];
topLabel.text = [NSString stringWithFormat:#"topLabel %d", i+1];
[topLabel sizeToFit];
[self.topLabelArray insertObject:topLabel atIndex:i];
[self.scrollView addSubview:topLabel];
topLabel.translatesAutoresizingMaskIntoConstraints = NO;
UILabel* bottomLabel = [[UILabel alloc] init];
bottomLabel.text = [NSString stringWithFormat:#"bottomLabel %d", i+1];
[bottomLabel sizeToFit];
[self.bottomLabelArray insertObject:bottomLabel atIndex:i];
[self.scrollView addSubview:bottomLabel];
bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;
UIButton* button = [[UIButton alloc] init];
button.titleLabel.text = [NSString stringWithFormat:#"button %d", i+1];
[button sizeToFit];
[self.buttonArray insertObject:button atIndex:i];
[self.scrollView addSubview:button];
button.translatesAutoresizingMaskIntoConstraints = NO;
UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[self.pageImages objectAtIndex:i]]];
imageView.frame = CGRectMake(0,0,200,200);
imageView.translatesAutoresizingMaskIntoConstraints = NO;
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.pageViews insertObject:imageView atIndex:i];
[self.scrollView addSubview:imageView];
NSDictionary* viewsDictionary = #{#"topLabel":topLabel,
#"bottomLabel":bottomLabel,
#"button": button,
#"imageView": imageView
};
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(10)-[topLabel]-(10)-[imageView]-(10)-[bottomLabel]-(10)-|"
options:0 metrics:nil
views:viewsDictionary]];
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:[button]-(10)-|"
options:0 metrics:nil
views:viewsDictionary]];
if (i==0)
{
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(10)-[topLabel]"
options:0 metrics:nil
views:viewsDictionary]];
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(10)-[imageView]"
options:0 metrics:nil
views:viewsDictionary]];
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(10)-[bottomLabel]-(10)-[button]"
options:0 metrics:nil
views:viewsDictionary]];
}
else if (i == self.pageImages.count)
{
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:-(10)-[topLabel]-(10)-|"
options:0 metrics:nil
views:viewsDictionary]];
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:-(10)-[imageView]-(10)-|"
options:0 metrics:nil
views:viewsDictionary]];
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:-(10)-[bottomLabel]-(10)-[button]-(10)-|"
options:0 metrics:nil
views:viewsDictionary]];
}
else
{
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:[prevTopLabel]-(10)-[topLabel]"
options:0 metrics:nil
views:#{#"prevTopLabel": [self.topLabelArray objectAtIndex: i-1],
#"topLabel": topLabel
}]];
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:[prevImageView]-(10)-[imageView]"
options:0 metrics:nil
views:#{#"prevImageView": [self.pageViews objectAtIndex: i-1],
#"imageView": imageView
}]];
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:[prevButton]-(10)-[bottomLabel]-(10)-[button]"
options:0 metrics:nil
views:#{#"prevButton": [self.buttonArray objectAtIndex: i-1],
#"button":button,
#"bottomLabel": bottomLabel
}]];
}
[self.scrollView addConstraint:[NSLayoutConstraint
constraintWithItem:topLabel
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:imageView
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0.0]];
[self.scrollView addConstraint:[NSLayoutConstraint
constraintWithItem:bottomLabel
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:imageView
attribute:NSLayoutAttributeCenterX
multiplier:0.8
constant:0.0]];
// [self.scrollView addConstraint:[NSLayoutConstraint
//

Ok, there's a few things wrong here:
else if (i == self.pageImages.count)
This clause will never run, as your loop count is set to break when i == self.pageImages.count -1, here for (int i=0; i<self.pageImages.count; i++).
Next
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:-(10)-[topLabel]-(10)-|"
options:0 metrics:nil
views:viewsDictionary]];
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:-(10)-[imageView]-(10)-|"
options:0 metrics:nil
views:viewsDictionary]];
[self.scrollView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:-(10)-[bottomLabel]-(10)-[button]-(10)-|"
options:0 metrics:nil
views:viewsDictionary]];
These will also produce invalid constraints, specifically #"H:-(10)-[bottomLabel].... is not pinning the furthest left constraint to anything. All visual format strings that connect views need to start or finish with a view. Either a subview ([subview]) or a superview (|). To fix this, you need to keep a reference to the previous pages label in the loop, and add that to the beginning of your VFL string. Something like this
#"H:[prevBottomLabel]-(10)-[bottomLabel]....
prevBottomLabel = bottomLabel;
// Continue loop
Next:
UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[self.pageImages objectAtIndex:i]]];
imageView.frame = CGRectMake(0,0,200,200);
imageView.translatesAutoresizingMaskIntoConstraints = NO;
imageView.contentMode = UIViewContentModeScaleAspectFit;
This will not have the desired effect, as you can't manually set the frame, then switch on autolayout. Currently, the frame value is ignored, and the height and width are set by the intrinsic content size of the image view, which will be the height and width of the image. If you want to set the height and width, you need to do it with constraints, as so:
[imageView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:[imageView(200)]"
options:0 metrics:nil
views:viewsDictionary]];
[imageView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:[imageView(200)]"
options:0 metrics:nil
views:viewsDictionary]];
That should give you some pointers, there may be other mistakes in there too but fixing these is a good place to start.

Related

How to add two views on each other with constraints

I am trying to add 2 views with same X, Y. They have space from the edge using addConstraints:[NSLayoutConstraint constraintsWithVisualFormat...]
I tried the strings "H:|20-[A][B]-20-[C]-20-[D]-20|" and V:|20-[A][B]-20-[C]-20-[D]-20|, and centreX == CenterX and centerY==centerY, but they kept conflicting, thinking that A and B should be next to each other.
A is hidden, and on some button clicked, B is hidden and A is shown.
To add views with same centre X,Y You need to first place one of the view say bView (Bottom view), using constatins
NSArray * bVerticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"|-20-[bView]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(bView)];
NSArray * bHorizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-20-[bView]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(bView)];
This places the bView in the superview with 20 as edge offset.
Now place the tView (top View) with same centre as of bView. Here self is the superview of bView and tView
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[bView]-(<=1)-[tView]" options:NSLayoutFormatAlignAllCenterX metrics:nil views:NSDictionaryOfVariableBindings(bView,tView)]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[bView]-(<=1)-[tView]" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(bView,tView)]];
Then pin the edges of tView with desired offset say 40
NSArray * tVerticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"|-40-[tView]-40-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(tView)];
NSArray * tHorizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-40-[tView]-40-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(tView)];
EDIT :
Here is how do do it.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
bView = [UIView new];
bView.backgroundColor = [UIColor redColor];
bView.translatesAutoresizingMaskIntoConstraints = NO;
tView = [UIView new];
tView.backgroundColor = [UIColor blackColor];
tView.translatesAutoresizingMaskIntoConstraints = NO;
// Firdt bView is added then tView hence tView is exaclty above the bView.
[self.view addSubview:bView];
[self.view addSubview:tView];
// Edges Constrints for bView
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|-20-[bView]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(bView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-20-[bView]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(bView)]];
// Edges Constints for tView
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|-20-[tView]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(tView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-20-[tView]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(tView)]];
// Centring for bView and tView
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[bView]-(<=1)-[tView]" options:NSLayoutFormatAlignAllCenterX metrics:nil views:NSDictionaryOfVariableBindings(bView,tView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[bView]-(<=1)-[tView]" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(bView,tView)]];
}
-(IBAction)toggleViews:(id)sender {
NSArray * subViews = self.view.subviews;
[self.view exchangeSubviewAtIndex:[subViews indexOfObject:tView] withSubviewAtIndex:[subViews indexOfObject:bView]];
}

How to do AutoLayout programmatically with Horizontal scrolling?

I'm trying to do Horizontal scrolling on iOS using AutoLayout programmatically. Here's the link to my github I'm trying to add another NewsSection to the next page but I'm not sure how to do it. Here's the code I'm working on.
- (void) setupNewsView
{
UIView *newsView = [[NewsSection alloc] initWithFrame:CGRectZero];
newsView.backgroundColor = [UIColor redColor];
UIView *anotherNewsView = [[NewsSection alloc] initWithFrame:CGRectZero];
anotherNewsView.backgroundColor = [UIColor blueColor];
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
newsView.translatesAutoresizingMaskIntoConstraints = NO;
anotherNewsView.translatesAutoresizingMaskIntoConstraints = NO;
self.scrollView.pagingEnabled = YES;
[self.scrollView addSubview:newsView];
[self.scrollView addSubview:anotherNewsView];
NSDictionary *viewsDict = #{ #"newsView": newsView, #"anotherNewsView": anotherNewsView };
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[newsView]|"
options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom
metrics:nil
views:viewsDict]];
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[newsView]|"
options:0
metrics:nil
views:viewsDict]];
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:newsView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView
attribute:NSLayoutAttributeWidth
multiplier:1.0f
constant:0.0f]];
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:newsView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView
attribute:NSLayoutAttributeHeight
multiplier:1.0f
constant:0.0f]];
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[anotherNewsView(200)]|" options:0 metrics:nil views:viewsDict]];
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[anotherNewsView(100)]|" options:0 metrics:nil views:viewsDict]];
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width * 2, self.scrollView.frame.size.height)];
Right now the app looks like this. What I want is user should be able to scroll to the right and see the blue screen. What constraint do I need to add?
The constraints you have set the blue view to fill the scroll view AND to be of a fixed width, which causes a conflict. The |s at either end of the constraint string make anotherNewsView hug the bounds of its superview (scrollView).
Try dropping the final |s from your constraints. Also position anotherNewsView to be left-aligned with newsView rather than scrollView.
These constraints should do the trick:
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[newsView(500)]" options:0 metrics:nil views:viewsDict]];
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[newsView(500)][anotherNewsView(100)]" options:0 metrics:nil views:viewsDict]];
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[anotherNewsView(200)]" options:0 metrics:nil views:viewsDict]];

UIScrollView does not scroll with AutoLayout

I can't make UIScrollView scroll vertically when using Autolayout, I've tried many suggestions. I've read Apple's technical note but even that doesn't seem to work with my pure auto layout approach.
Here is my simple code where I'm adding two UIView blocks1 & 2 in a container view. The container view itself is the only child of the UIScrollView as suggested by many references online. I set the heights of block 1 and 2 as 800 points each, but the scroll view won't scroll.
- (void)viewDidLoad {
[super viewDidLoad];
// Test UIScrollView with Autolayout, scrolling should word
UIView *mainView = self.view;
UIScrollView* scrollView = [UIScrollView new];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:scrollView];
UIView* contentView = [UIView new];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
contentView.backgroundColor = [UIColor greenColor];
[scrollView addSubview:contentView];
UIView* block1 = [[UIView alloc] init];
block1.translatesAutoresizingMaskIntoConstraints = NO;
[block1 setBackgroundColor:[UIColor blackColor]];
[contentView addSubview:block1];
UIView* block2 = [[UIView alloc] init];
block2.translatesAutoresizingMaskIntoConstraints = NO;
[block2 setBackgroundColor:[UIColor blackColor]];
[contentView addSubview:block2];
NSDictionary* viewDict = NSDictionaryOfVariableBindings(mainView,scrollView, contentView, block1, block2);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrollView]|" options:0 metrics:0 views:viewDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrollView]|" options:0 metrics:0 views:viewDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[contentView(==mainView)]|" options:0 metrics:0 views:viewDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[contentView(==mainView)]|" options:0 metrics:0 views:viewDict]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[block1(==300)]" options:0 metrics:0 views:viewDict]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[block1(==800)]" options:0 metrics:0 views:viewDict]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[block2(==300)]" options:0 metrics:0 views:viewDict]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-810-[block2(==800)]" options:0 metrics:0 views:viewDict]];
}
Looking to your code, It seems that the size of you content view will be of same size as UIView.
e.g. : IF Device screen height is 568 then your content view size will be 568, and you are set your block2 at y position = 180.
Your Code:
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[contentView(==mainView)]|" options:0 metrics:0 views:viewDict]];
change:
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[contentView(2000)]|” options:0 metrics:0 views:viewDict]];
Hope it solves your problem if any further query please let me know.
If all you want to do is make a scroll view work with auto layouts, you can try this.
http://natashatherobot.com/ios-autolayout-scrollview/
Do the following changes in your code
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[contentView]|" options:0 metrics:0 views:viewDict]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-810-[block2(==800)]|" options:0 metrics:0 views:viewDict]];
Hope this helps

How come my constraints are not working? iOS

I am just trying to set a width and a height constraint on my imgView. I have the following code:
UIImageView *imgView = [[UIImageView alloc] init];
imgView.center = self.view.center;
imgView.image = [UIImage imageNamed:#"favorites5-highlighted.png"];
imgView.contentMode = UIViewContentModeCenter;
[self.view addSubview:imgView];
// width constraint
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[imgView(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(imgView)]];
// height constraint
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[imgView(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(imgView)]];
I end up getting this error: Unable to simultaneously satisfy constraints.
I looked up SO and tried adding:
imgView.translatesAutoresizingMaskIntoConstraints = NO;
and
self.view.translatesAutoresizingMaskIntoConstraints = NO;
EDIT:
I am just trying to set the width and height of the imageView to the desired properties. I first tried using
CGRect rect = CGRectMake(0, 0, 10, 10);
imgView.frame = rect;
but nothing changed
Two issues:
You do want:
imgView.translatesAutoresizingMaskIntoConstraints = NO;
You do not want:
self.view.translatesAutoresizingMaskIntoConstraints = NO;
Your attempt to set center is for naught, as when constraints are applied, this will be lost. Unfortunately, you don't define constraints to define the location of the image view. You might do that with the last two lines of the block below:
UIImageView *imgView = [[UIImageView alloc] init];
//imgView.center = self.view.center; // this does nothing in auto layout
imgView.image = [UIImage imageNamed:#"favorites5-highlighted.png"];
imgView.contentMode = UIViewContentModeCenter;
imgView.translatesAutoresizingMaskIntoConstraints = NO; // add this line
[self.view addSubview:imgView];
NSDictionary *views = NSDictionaryOfVariableBindings(imgView);
// width constraint
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[imgView(100)]" options:0 metrics:nil views:views]];
// height constraint
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[imgView(100)]" options:0 metrics:nil views:views]];
// center align
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:imgView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:imgView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];

Center views using *only* visual format?

I'm trying to center 2 views with different height vertically.
UILabel *view1 = [[UILabel alloc] init];
view1.backgroundColor = [UIColor redColor];
view1.text = #"view1\nline2";
view1.textAlignment = NSTextAlignmentCenter;
view1.numberOfLines = 0;
UILabel *view2 = [[UILabel alloc] init];
view2.backgroundColor = [UIColor greenColor];
view2.text = #"view2\nline2";
view2.textAlignment = NSTextAlignmentCenter;
view2.numberOfLines = 0;
[self.view addSubview:view1];
[self.view addSubview:view2];
NSDictionary *views = #{#"view1": view1, #"view2" : view2};
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
for (UIView *view in views.allValues) {
[view setTranslatesAutoresizingMaskIntoConstraints:NO];
}
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[view1]-[view2(==view1)]-|"
options:NSLayoutFormatAlignAllCenterY
metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(>=20)-[view1(200)]-(>=20)-|"
options:NSLayoutFormatAlignAllCenterY
metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(>=20)-[view2(100)]-(>=20)-|"
options:NSLayoutFormatAlignAllCenterY
metrics:nil views:views]];
This manages to make the centers of both aligned vertically, but they are at the bottom of the superview!
I want to center vertically not only relative to each other, also in the superview.
I added a constraint like this and it works:
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:view1
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1
constant:0]];
But I want to know, is this possible to achieve using only with visual format?
Yes, it's possible, but only by adding spacer views. So if you create a couple of views, lets call them spacer1 and spacer2, you can center view1 with this string,
#"V:|[spacer1][view1][spacer2(==spacer1)]|"
This assumes that view1 has a fixed height. I wouldn't recommend doing it this way though, I would just use the code you show at the bottom of your post.
What about calculating the Y in "metrics" ?
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-centerY-[view1(200)]-(>=20)-|"
options:NSLayoutFormatAlignAllCenterY
metrics:#{#"centerY": #(CGRectGetHeight(self.view.frame)/2.0 - 100)}
views:views]];

Resources