autolayout - make height of view relative to half superview height
This is now possible in IB as of [at least] Xcode 5.1.1. Although it took me sometime to figure out it is actually super simple:
First create a basic top alignment constraint (you will also need to setup bottom, left, and right constraints, like normal)
. Then select the constraint and navigate to the Attribute inspector:
Then you can adjust the multiplier. If you want it 50% of the super view leave it at 1
, since it is aligned per the super's center. This is also a great way to create views that are other percentages too (like 25% of super view)
How to setup a view with a half of screen height?
Try to change heightConstraint
's constant value in viewDidLayoutSubviews
method.
override func viewDidLayoutSubviews() {
heightConstraint.constant = self.view.frame.size.height / 2
}
In autolayout, how can I have view take up half of the screen, regardless of orientation?
The first half of the answer address the case in which we want to split the view evenly between view A (blue) and view B (red). The second half will address the case in which we want to have view A take up half the screen, but view B does not exist.
Step 1:
Set up blue's auto-layout constraints as pictured. Top, left, bottom of 0 to the superview. Right of 0 to the red view.
Step 2:
Set up the same, but mirrored, constraints for the red view.
If you've completed the first two steps correctly, you should have some auto-layout errors and warnings:
We need one more constraint to fix these errors/warnings and get what we need.
Step 3:
Hold control, click and drag from one view to the other and select "equal widths". Now our views will always maintain the same width. All of our auto layout warnings and errors disappear, and our views will always be half the screen no matter the orientation or device.
To add these constraints in code using VFL, we need the following constraints:
@"H:|[blueView(==redView)][redView]|"
@"V:|[blueView]|"
@"V:|[redView]|"
Now, suppose the case where we want a single view to take up half the screen, but we don't have a view for the other half. We can still do this with auto layout, but it's a slightly different set up. In this example, our view is blue, and its parent view is green.
Step 1:
This is similar to step 1 above, except we don't add a right side constraint (this will obviously vary if we want our view to take up a different half).
Step 2:
Like before, we want to assign an "equal widths" constraint. In this case, from our view to the parent view. Again, hold control and click drag from one to the other.
At this point, we have an auto layout warning. Auto layout wants our frame to match its parent's width. Clicking the warning and choosing "Update constraints" will put a hardcoded value in. We don't want this.
Step 3:
Select the view and go to its size inspector. Here, we'll be able to edit the constraints.
Click "Edit" next to the "Equal Width to:" constraint. We need to change the multiplier value.
We need to change the multiplier value to 2.
The constraint now changes to a "Proportional Width to:", and all of our auto layout warnings and errors disappear. Now our view will always take up exactly half of the super view.
To add these constraints in code, we can add some using VFL:
@"H:|[blueView]"
@"V:|[blueView]|"
But the proportional width constraint can't be added with VFL. We must add it as such:
NSLayoutConstraint *constraint =
[NSLayoutConstraint constraintWithItem:blueView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:superView
attribute:NSLayoutAttributeWidth
multiplier:2.0
constant:0.0];
Set up height constraint for superview based on child views
you do it by constraining the first label's top to self's top and then the last label's bottom to self's bottom. each of the labels in between have their top constrained to the previous label's bottom.
@interface SomeView: UIView
@end
@implementation SomeView
- (instancetype)init {
self = [super init];
if (!self)
return nil;
// create an array of random labels
NSArray <UILabel*> *labels = [self labelsWithRandomText:10];
// add each label to the view, setting it's top to the previous view's bottom
UIView *previousView = self;
for (UILabel *label in labels) {
[self addSubview:label];
// bound the left and right of the label to match the parent view
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(label)]];
// if this is the first label being added, set its top to self's top
// otherwise set its top to the bottom of the previous view
NSLayoutAttribute previousAttribute = previousView == self ? NSLayoutAttributeTop : NSLayoutAttributeBottom;
[self addConstraint:[NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:previousView attribute:previousAttribute multiplier:1 constant:0]];
// update previous view
previousView = label;
}
// constrain self's bottom to the bottom of the last label
[self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:previousView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]];
return self;
}
// create an array of labels w/ random color and background text
- (NSArray <UILabel *> *)labelsWithRandomText:(int)labelCount {
NSMutableArray <UILabel*> *labels = [NSMutableArray new];
for (int i = 0; i < labelCount; i++) {
UILabel *label = [UILabel new];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.numberOfLines = 0;
label.backgroundColor = [self randomColor];
label.text = [self randomString];
[labels addObject:label];
}
return labels;
}
// create random color
- (UIColor *)randomColor {
return [UIColor colorWithRed:(arc4random()%255)/255. green:(arc4random()%255)/255. blue:(arc4random()%255)/255. alpha:1];
}
// create random string
- (NSString *)randomString {
static NSArray <NSString*> *words;
static NSInteger wordCount;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
words = @[@"cat ", @"dog ", @"bird ", @"went ", @"home ", @"with ", @"under ", @"red ", @"blue ", @"green "];
wordCount = [words count];
});
NSMutableString *randomString = [NSMutableString new];
// create somewhere between 10-30 words
int randomWordCount = arc4random() % 20 + 10;
for (int i = 0; i < randomWordCount; i++) {
[randomString appendString:words[arc4random() % wordCount]];
}
return randomString;
}
@end
Set subview height relative to parent view in Storyboard
Add a height constraint whose multiplier value is 1/3
so the image view's height will be one third of its superview's height.
--
Here is how it looks with different device sizes:
How do I use auto layout to start a view in the half of its superview?
I don't think you can do this in Interface Builder, but this is pretty easy to do by creating the constraints in code.
Your first equation is exactly how I would express the constraint. The second equation might work, but it is weird to relate an origin to a width. They are different quantities. Instead, just pin the right of the innerView to the right of the outerView.
We use the attribute NSLayoutAttributeTrailing
instead of NSLayoutAttributeRight
, so your interface will properly flip when localized RTL.
// innerView.width = outerView.width * 0.5
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:innerView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:outerView
attribute:NSLayoutAttributeWidth
multiplier:0.5
constant:0];
// innerView.trailing = outerView.trailing
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:innerView
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:outerView
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:0];
[outerView addConstraints:@[widthConstraint, rightConstraint]];
Related Topics
Implement Pushkit and Test in Development Behavior
How to Put an Image in a Realm Database
Add Custom Header Field in Request of Avplayer
Install Simulator Sdk 4.3 to Xcode 4.4 on Mountain Lion
How to Implement Auto-Complete for Address Using Apple Map Kit
"Untrusted App Developer" Message When Installing Enterprise iOS Application
Didreceiveremotenotification Not Working in the Background
Date to Milliseconds and Back to Date in Swift
How to Create Negative Firebase Timestamp in Swift
Firebase Cloud Messaging - Check Existing or Available Topics
How to Manually Deprecate Members
Using Audiobufferlist with Swift
Passing Data to View Controllers That Are Embedded in Container Views
iOS Nsdate() Returns Incorrect Time
Filemanager Cannot Find Audio File
Xcode 8 :Function Types Cannot Have Argument Label Breaking My Build