AutoLayout two labels with 30:70 ratio proportional - ios

I have two labels green and yellow and i am trying to make them always be in the same proportional to the screen width. I tried aspect ratio and changing the priority etc but not get the final result. I will be very thankful if someone can help me

You need to set up constraints for the widths of the views related to the width of the superview.
In your case:
Pin the left side of the green view to the view.
Pin the right side of the yellow view to the view.
Make the horizontal spacing between the green and yellow views to be zero.
Now create a constraint and apply it:
- (void)viewDidLoad {
[super viewDidLoad];
[self setupWidthConstraints];
}
- (void)setupWidthConstraints {
NSLayoutConstraint *widthConstraint;
widthConstraint = [NSLayoutConstraint constraintWithItem:self.greenView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:0.30
constant:0.0];
[self.view addConstraint:widthConstraint];
}
This constrains the green view's width to 30% of the view width. And since the yellow view is pinned to the side and the green view, it will take up the remaining 70%.
If you want to see this in action you can get an example project that demonstrates exactly this from https://bitbucket.org/abizern/so27659421/get/master.zip

Related

Interface Builder Constraints

I'm trying to create layout like this in interface builder.
I'm using constraints to make these views stretchable.
Top view has left, right and top space bound to superview, and bottom space to bottom view.
Bottom view has the left right and bottom space bound to superview.
On runtime I add ViewController views to both of them.
Issue here is that there is no constraint for Y of bottom view, IB shows red error arrow and so on. That is because I don't know exact height of it. Is there any "android wrap_content" constraint for yellow view to be with height which is equal to it's inner view added in runtime?
Add a constraint for the height of the yellow view. Then add an IBOutlet for that constraint so you can make changes to the constraint's constant value at runtime. If you need to calculate the size that satisfies the yellow view's constraints, you can use systemLayoutSizeFittingSize:.
Alternatively, you can rely on the yellow view's intrinsicContentSize. Add a placeholder Intrinsic Size for the view in Interface Builder. If your yellow view implements intrinsicContentSize or has constraints that give it an unambiguous height (e.g. if it contains a UILabel or UIImageView that is pinned at the top and the bottom), then that will be enough to appropriately size the view.
Just add height constraint to yellow view, for example:
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self.yellowView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeHeight
multiplier:0.20f
constant:0.0f];
heightConstraint.active = YES;

How to configure a UIScrollView content size to have a fixed width and a dynamic height?

I have a UIScrollView contained in another container view with constraints set to take all the space of the container view. That is to say that I don't have a fixed width or height on the scroll view.
In my scroll view I programmatically add subviews. Each subview (content view) is loaded from a xib.
In the xib I set an arbitrary size to the root view (500x500) but I would like that view width to be automatically resized to the scroll view width (the scroll view width being the container width).
I don't want the user to be able to scroll horizontally.
I tried different solutions always resulting in the scroll view being scrollable horizontally.
I tried to tweak the content view hugging and compression property to different values on the horizontal axis with no success.
I don't want to set fixed widths on my views because I want them to take the width of the container view.
Thanks in advance if you have any suggestions.
Late answer with what I came up with at that time.
As I'm using Autolayout, VChemezov answer is not really satisfying.
My content views have a top, bottom, leading, width set of constraints. (width instead of trailing which is what I was doing in the first place but it was not working).
So now I have something like this:
NSLayoutConstraint *leading = [NSLayoutConstraint
constraintWithItem:messageView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.conversationScrollView
attribute:NSLayoutAttributeLeading
multiplier:1.0f
constant:0.0f];
NSLayoutConstraint *width = [NSLayoutConstraint
constraintWithItem:messageView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.conversationScrollView
attribute:NSLayoutAttributeWidth
multiplier:1.0f
constant:0.0f];
[self.conversationScrollView addConstraints:#[ top, leading, width ]];
With the width of the content view equal to the width of the scroll view.
Autolayout will not adjust view size inside UIScrolView. You should layout and resize this views by yourself. There is two basic solutions:
Explicitly set width of subview before adding it to UIScrollView
Subclass UIScrollView and override setFrame and layoutSubviews like this
#implementation MyScrollView
- (void)setFrame:(CGRect)frame{
[super setFrame:frame];
[self setNeedsLayout];
}
- (void)layoutSubviews{
[super layoutSubviews];
NSArray * subviews=self.subviews;
for(UIView * view in subviews){
CGRect viewFrame=view.frame;
viewFrame.size.width=self.bounds.size.width;
view.frame=viewFrame;
}
}
#end
Using SnapKit it is even faster:
let helper = UIView()
scrollView.addSubview(helper)
helper.snp.makeConstraints { make in
make.width.equalTo(snp.width)
make.leading.trailing.top.equalToSuperview()
make.height.equalTo(0)
}

iOS Autolayout: Align left edge of a UILabel with horizontal center in container?

So I'm trying to have a customized UITableViewCell that looks like the following:
And I'm trying to get the Detail labels to be left aligned and set the content hugging on the title labels higher.
So the challenge I have is that I want the left edge of the second column on Title cells to be aligned with the center of the whole view.
Is there a way to do that?
Try using a couple of grouping views, one for each column. Pin the outer edges of each column view to the edges of the cell content view, then add an equal-widths constraint to the column views.
Once you have your containing column views in place, you can layout the labels inside each.
Add equal widths constraint, add leading space constraint to left view, and trailing space to the right, and horizontal spacing between them.
Sure, you could put them in a UIView and that views left edge would be equal to CenterX and thus they would be aligned in the middle. Or you could just align the top title cell to CenterX and have the leading edge of each title match that. There are numerous ways you can achieve what your asking here.
NSLayoutContraint *constraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f];
[self.view addConstraint:constraint];
NSArray *constraints [NSLayoutConstraint
constraintsWithVisualFormat:#"V:|[label1]-(5)-[label2]-(5)-[label3]|"
options:NSLayoutFormatAlignAllLeading
metrics:nil
views:#{ #"label1" : label1, #"label2" : label2, #"label3" : label3 }];
[self.view addConstraints:constraints];
Above is just samples of how you could do it in the code if you wished too, self.view is a view but if you wanted the content view of the UITableViewCell you could just switch it out to that.
I couldn't get the suggestions above working so I did this another way.
InnerView1 50% width of ContentView & pinned to left
InnerView2 50% width of ContentView & pinned to right
Simple.

can I set constraints directly to superview in a custom view?

A pretty simple question I reckon:
one UIViewController
one custom UIView
The controller only does:
-(void)loadView{
[super loadView];
self.sideMenu = [[sideMenuView alloc]init];
[self.view addSubview:self.sideMenu];
}
and in the UIView I would like to do something like:
self.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeLeading multiplier:1 constant:100];
[self.superview addConstraint:constraint];
So that when I create the UIView in the controller its constraints is already set in relation to the controller.
I have tried and nothing crashes but the UIView gets realy weird x and y coords
Maby I need to update the constraints? Or maby this isnt at all possible?
I'm not sure what ui behavior you are exactly looking for since it appears that you are trying to tie the leading space of your view to the leading space of it's superview. Being the leading space, the space on the left of the view, could it be that you are looking for the more common "stick my left side 100 pixels from my parents left border"? Anyway, in either case, I would connect an outlet from the controller to the custom view (i.e. myCustomView below) and then build the constraint in the UIViewController and not the UIView by overriding:
- (void)updateViewConstraints {
[super updateViewConstraints];
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:myCustomView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:myCustomView.superview
attribute:NSLayoutAttributeLeading
multiplier:1
constant:100];
[myCustomView addConstraint:constraint];
}
Apple has an interesting page with a table showing the various runtime entry points for autolayout at this address:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/Articles/runtime.html#//apple_ref/doc/uid/TP40010853-CH6-SW1
You might consider adding other constraints as well. Auto layout has the the tendency to exploit any freedom you leave unchecked in the worst possible way ;-)
So leading edge is not enough.
You need enough constraints to satisfy vertical and horizontal layout.
In one direction you need at least
one edge & width (or hight)
Or
Two edges ( implicit width or height )
Or
A horizontal (or vertical) center based constraint and an explicit width ( or height respectively)
The thing about width and height is that they can also be determined by intrinsic content size.
Add constraints after adding the view to the superview.
A bit late but PureLayout is pretty handy https://github.com/smileyborg/PureLayout

autolayout update image size when rotating

I'm very new with auto layout. I have a simple UIViewController that contains a View and a UIImageView.
On portrait mode this image is 320x115px but I would like to reduce the image height when rotating to landscape.
Currently I have the following constraints on my image.
-Height Equals 115px
-Trailing Space to superview
-Leading Space to superview
-Top Space to supverview
How to make my UIView have proportional vertical size when rotating from portrait to landscape?
Thanks for your help,
Sébastien.
If you want the same proportional size as 115 is to 480 (0.24), then you use the multiplier parameter in constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:.
In the example below, I made an IBOutlet to the height constraint in IB (heightCon), then remove that in code and add another one that is based on a fraction of self.view's height (iv is my outlet to the image view):
- (void)viewDidLoad {
[super viewDidLoad];
[self.iv removeConstraint:self.heightCon];
NSLayoutConstraint *newHeightCon = [NSLayoutConstraint constraintWithItem:self.iv attribute:NSLayoutAttributeHeight relatedBy:0 toItem:self.view attribute:NSLayoutAttributeHeight multiplier:.24 constant:0];
[self.view addConstraint:newHeightCon];
}

Resources