Imagine this following scenario. You have a UIImageView and a UIButton. The first is 300x360, the second is 210x70. The imageview
contains a catalog image, the button
says "open catalog".
I would like to position elements in the main view according to these requirements:
the two elements should be centered horizontally, namely the center.x coordinates should be all equal (view, image and button);
the two elements should be centered vertically in the following way: separator (flexible) - imageview - separator (fixed, let's say 30 pts) - button - separator (flexible). The topmost and bottommost separator should have the same size (this is the meaning of centered).
I cannot make this to work using NSLayoutConstraint.
So far, what I did, has been centering the X coordinate of the two elements using NSLayoutAttributeCenterX
and NSLayoutRelationEqual
to the same view
attribute.
The last part, according to my idea, is to fix their vertical alignment.
I tried using @"V:|-[imageview(360)]-[button(70)]-|"
but it won't work (Unable to simultaneously satisfy constraints.
).
If I use @"V:|-[imageview(360)]-[button]-|"
I get everything partially ok. Namely, the top part is perfect but the button is stretched so to fill the gap between the internal separator and the bottom of the view.
How can I make those elements to be fixed-sized and to let Auto-layout to just figure out how to place them in the view?
I was able to do it by doing something like this:
NSNumber *sepHeight = @60.0F;
// Center the two views horizontally
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:imageView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:button
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0]];
// Position the two views one below the other, using the separator height defined above
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[imageview]-sepHeight-[button]"
options:0
metrics:NSDictionaryOfVariableBindings(sepHeight)
views:views]];
// Force the button distance from the bottom to be the half of the size of the content
CGFloat constant = (imageview.frame.size.height + button.frame.size.height + [sepHeight floatValue]) / 2.0;
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:button
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1
constant:constant]];
The tricky part is the constant value. That value is the half of the height of all the views, including their separators. This means that, if the imageview's height is 360, the button's height is 70 and the separator is 60, that constant will be (360 + 70 + 60)/2 = 245.
There should be a smarter way, indeed, but for now I think this is ok.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With