I'm trying to figure out how to use Autolayout and I've founded a problem. I want to create a view in IB with size 200x200. This view, called them PieView, has two UIImageViews with frames (0, 0, 200, 200), for both of them.
My question is, how to override updateConstraints in code (I like visual format language), or in IB, that if I change size of my PieView (for example to 100), and subviews will changed too (0, 0, 100, 100).
And how can I change the size of PieView, I'm trying for width and for height
NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0f
constant:100.f];//kDiameter * sizeCoef];
If the subviews of the container view (PieView) are correctly positioned/sized/pinned relative to their container, all you need to do is update the width of the container view (PieView).
To change the view's size in code, you'll need to make sure you keep a reference (in a property, for example) to the constraint on the view's width. So if you added that constraint in Xcode, that means connecting an outlet for that constraint. Or if you added it in code (as you have written in your question), just assign the constraint to a property instead of a local variable.
Then, in updateConstraints, change the constant property of the constraint to the new width. Here's an example:
- (void)updateConstraints
{
// Probably want to wrap the below line with a check for when you should actually do this change,
// as updateConstraints may get called more than once (including when you aren't ready to change the width).
self.widthConstraint.constant = 100.0f;
}
Then just call setNeedsUpdateConstraints on the view when you're ready to change its width!
I'm not sure that you even need to re-configure the height or width constraints for the image views. If you want the image views to grow and shrink with their superview, then just pin the the sides of the images views to the superview in IB. You would not need to override updateConstraints.
Related
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;
I had an app contains a tableview that takes place part of the screen's area.
How to make the tableview's width always keeps 1/3 of the screen size whatsoever on iPad2 and iPad Air? Besides, how to make it through auto layout feature in iOS?
create an equal widths constraint with the tableView and its parent view (or the viewController's view, depends on what you want). Edit the the constraint and change the multiplier to either 0.3333 or 3 depending on which view is the constraint's first item, though, i think the super view is always the first item, in that case use 3 as the multiplier.
or programmatically through,
[NSLayoutConstraint constraintWithItem:mainView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:tableView attribute:NSLayoutAttributeWidth multiplier:3 constant:0];
and by the way here's the image of the attributes inspector (where you can change the multiplier) when a constraint is selected on IB,
let width = self.view.frame.width / 3
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[yourItem(==width)]|",
options: nil, metrics: nil, views: ["yourItem":yourItem]))
So I have been moving parts of the code to use constraints rather than the older way of doing things using frames. This is the current code that I need to move. I need to change the height of the view when I hide\unhide the tabbar below when the user presses a button.
CGRect newFrame = self.view.frame;
newFrame.size.height += 44
self.view.frame = newFrame;
self.view is the UIViewController. I want to set the height of the view shown in the picture. There is no way to add a height constraint to it (you can set it on the subviews though easily which i dont want)
I don't see a way of setting the self view height using constraints.
thanks
arpit
This short tutorial will be helpful for you.
You can do it using VFL (I personally prefer, see link above) or by this kind of code:
[yourView addConstraint:[NSLayoutConstraint constraintWithItem:yourView
attribute:NSLayoutAttributeHeight
relatedBy:0
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:requiredHeight]];
This piece of code will add a constraint on height for yourView specified by requiredHeight. Before start coding please take a look at intrinsicContentSize and updateConstraints methods.
When setting constraints please remember to firstly set (for a view you will set constraints) translatesAutoresizingMaskIntoConstraints flag to NO (it is set to YES by default). Also reading this should put some light on the topic.
I have a view like in attached image
Now I am adding constraints such that the UITextview in the view has to be on the right hand side of the screen when orientation is changed to landscape. On UItextview, I have added below constraints,
Trailing Space to : Superview
Bottom Space to : Superview
These constraints though displayed some warnings on ambugity, did the job for me. Below is the screenshot of landscape mode.
My problem is though the UItextview is moved to right side, I want some additional width from top of superview when it is in landscape mode. In other words, I want the UITextview to be moved a little downward from where it is now in landscape mode. I am pondering how to do that using auto layout in IB and I am not able to figure that how.
Any suggestions please.
You can do this with constraints in several ways, but there's no way to do this automatically with just constraints you make in IB. By using both the multiplier and constant values in the method, constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:, you can have one constraint that evaluates to different distances in portrait and landscape. It's a pain to do the calculations to figure out what to use for those values, so I've written a category on NSLayoutConstraint to do that. An example of one of those methods, is this:
+(NSLayoutConstraint *)topConstraintForView:(UIView *)subview viewAttribute:(NSLayoutAttribute) att superview:(UIView *)superview portraitValue:(CGFloat)pValue landscapeValue:(CGFloat)lValue {
CGFloat multiplier = (pValue - lValue)/(superview.bounds.size.height - superview.bounds.size.width);
CGFloat constant = pValue - (superview.bounds.size.height * multiplier);
NSLayoutConstraint *con = [NSLayoutConstraint constraintWithItem:subview attribute:att relatedBy:0 toItem:superview attribute:NSLayoutAttributeBottom multiplier:multiplier constant:constant];
NSLog(#"top coeffs: %f %f",multiplier,constant);
return con;
}
The way you use these, is to add the starting portrait constraint in the storyboard, but check the box, "Placeholder - Remove at build time" in the attributes inspector for the constraint, and then replace it in viewDidLoad, like this:
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addConstraint:[NSLayoutConstraint topConstraintForView:self.textView viewAttribute:NSLayoutAttributeTop superview:self.view portraitValue:225 landscapeValue:50]];
}
This will automatically adjust the position of the text view based on the rotation of the device without any further code. You might have to change the width of the text fields to get everything to fit properly -- I enclosed them and the "Get" labels in a view to more easily position them as a group. That view and the text view had height and width constraints, as well as top and left for the view, and top and right for the text view. The category has methods to adjust the other constraints as well, and can be found at http://jmp.sh/b/S4exMJBWftlCeO5GybNO.
The other way to do this, is to make IBOutlets to the constraints you make in IB, and adjust them (the constant value), or delete some and remake other ones, in one of the rotation callback methods.
I'm trying to use programmatic visual constraints to display a label and a button next to one another. However, the UIImageView used as the button's background is making the intrinsic size of the button much too large.
I attempted to add a constraint that forces the height of the button to match the height of the label. But I just got a super tall label instead of a smaller button.
How do I set a constraint so that the button height is the same height as the label (and not vice-versa)
The button should keep the original aspect ratio of the image - its width should also match its own height (maybe this comes for free?)
The following works for this:
Set a width for the button in the visual layout: #"|-[titleLabel][refreshButton(==26)]"
Add a constraint such that the height of the button is equal to its own (now explicit) width:
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:refreshButton
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:refreshButton
attribute:NSLayoutAttributeWidth
multiplier:1.0f
constant:0.0f];
I would still prefer a solution that uses the label's height, instead of a fixed value.