Autolayout on a sub view prevents the whole window from being resized - objective-c

I have a simple view with a few labels, textfields and a big NSTextField that spans across the remaining interface.
I can setup auto layout so that the text field spans over the width of the window, but as soon as I add the last contraint Bottom space to container to its super view the window can no longer be resized.
These are my constraints:
So currently I have to omit this constraint and I end up with the following result:
See Screenshot

You need to fiddle with priorities on the constraints. Especially consider doing this on the height constraint.

Related

Handling autolayout special case

I have established constraints to like buttons, timestamp button, etc. below bottom of textfield a certain distance. You can see the issue in the image; if the textfield doesn't have enough letters, they overlap, how do I fix this? Here's a link to image:
https://docs.google.com/document/d/1_btZBSsL3SQA1IulFTasMFBghF_2hJYzrFlbuQPkKrM/edit?usp=sharing
The problem is setting the constraints with respect to the bottom of textfield. That bottom moves depending on the amount of text the field has and if that bottom position is above the bottom position of the icon to the left of the text field, you'll get the overlap you see. The solution, you might think, is to set the constraints with respect to the bottom of the icon but that won't work when the text field has a lot of text. You should try that just to understand the problem more clearly.
The actual solution is to set this particular constraint programmatically, as text is entered into the text field. You want to set that constraint with respect to the bottom of the view (icon or text field) that has the lowest bottom. That way, with little text, the constraint is set relative to the bottom of the icon but when there's enough text for the text field to vertically extend below the icon, the constraint is set relative to the text field instead.
Where would you set this constraint programmatically? Probably in the textField:shouldChangeCharactersInRange:replacementString: delegate method of UITextField.
Alternatively - and perhaps a better solution - you could have a view containing the icon and the text field and set the constraint in question with respect to the bottom of the container view. That way you can set the constraint in IB rather than have to do it programmatically.
To clarify my answer, after the discussion in the comments below, here's a picture of what I mean by having container views and setting constraints between them to avoid the observed overlap.
Set appropriate constraints within each of the container views then set constraints between the container views and between them and the cell content view (I'm assuming, from your picture, that you have all of this in a table view so you have some template table view cell).

Interface Builder Constraints --> UITextView flattening out when run

So I am using interface builder (which I don't often use), and I have two storyboards, one for iPhone 5+ and one for iPhone 4. The iPhone 5 one works perfectly.
However, when I run the app in an iPhone 4 or 4s, one of the UITextViews shrinks in size like it has deflated. When I use constraints, I usually put the views where I want them then do Editor -> Resolve AutoLayout Views or something, and normally the views snap into place.
Here is what it looks like in IB:
IB constraints
And this is what I get when I run the app:
The UITextView when I run the app
This is probably a really simple mistake, but I do feel like a bit of a doompf with my pancake like UITextView. Does anyone know what constraints I could add/actions I could take in order to make the UITextView the size it is in the storyboard?
I am in Xcode 6 and I am using auto layout.
Thanks in advance,
Edit Solved:
Firstly, I deleted the 3.5 inch storyboard so I only have one storyboard.
Then I selected the view in question, and fiddled around with the different iPhone sizes. Once I had put constraints that look good on all the devices, I ran it on every phone, and it worked :).
I agree with #Minestroni-Soup that you don't necessarily need to use two distinct storyboards. In any case, here's how I'd approach the problem. First, I'll ignore the horizontal direction because your problem happens in the vertical direction. If you have problems with the horizontal direction, post a new question.
Place constraints of fixed heights between vertically adjacent views in your layout, and also between the top view and the top border, and also between the bottom view and the bottom border. Then create a constraint that sets the height of one UITextView to be the same as the height of the other UITextView. That should solve your problem.
top border
constraint to set a vertical space of some amount
label 1
constraint to set a vertical space of some amount
textview 1
constraint to set a vertical space of some amount
label 2
constraint to set a vertical space of some amount
textview 1
constraint to set a vertical space of some amount
bottom border
Note that the above, alone, doesn't uniquely define the heights of the two text views but if you add a constraint that sets their heights to be the same, then all the constraints together will have a unique solution (because the labels have well-defined default heights).
I hope my explanation is clear enough.

Is there a way to shrink a constraint with autolayout without code?

Without using code, I'm basically trying to achieve the "Desired outcome" in this picture:
I want the constraint on the "Hello!" label to shrink its length when the screen height is shorter.
As you can see in "Actual result", the Button in the bottom is off the screen. I want the image view to have fixed width and height.
I know I can create IBOutlets for constraints and doing it by code like this kind of posts suggest (autolayout - make height of view relative to half superview height), but I'm trying to avoid using code as much as possible.
Side question: If there's no way to do this in IB, what are the best ways to do this in code?
Thanks for the help!
Yes. The easiest way to have this kind of "split height" constraint is to put a "header" view between your image view and the top of the screen, and embed your "Hello" label inside this new header view. Then add a constraint to keep the "Hello" label vertically centered inside the header view.
To keep the header view the right size, add constraints to keep the top of the header view pinned to the top of the screen, and the bottom of the header view to the top of the image view.
Then you'll just add constraints to keep the button and image view pinned to the bottom of the screen. (Or, see comment from Sulthan, below.)
In Xcode 5.1 (in beta), there is UI to make more general constraints, including the ones you want, but you have to do it like this or in code in earlier versions.

dynamically load UICollectionView in xcode

We have a label followed by a UIViewCollection. The height of the label is dynamically set based on its content. Based on the height of the label, we want to start the UIViewCollection as soon as the label ends. We are tracking the label x, y, width and height and adding some padding to y in the code to calculate the start of UIViewCollection. However, UIViewCollection does not move at all. Is it because of the specified storyboard? We tried it in ViewDidLoad and ViewWillAppear.
Also, if we replace the UIViewCollection with a label such that there are 2 labels one below another, we are able to dynamically load the start of the 2nd label if the code is placed in ViewWillAppear.
Please can someone help with moving the UIViewCollection up or down based on the previous label height?
Thanks in advance.
It may be because You use autolayout. You can switch off autolayout or set translatesAutoresizingMaskIntoConstraints YES for UIViewCollection, and than set current location
If you're using auto layout this is easy to do, and you don't need to do anything in code to keep track of the label's height. The label should have a height constraint to the top of the view and a spacing constraint to the top of the collection view (the length of that constraint will give you whatever padding you want between them). The collection view then needs a constraint to the bottom of the view. This setup will cause the collection view to get shorter when the label gets taller. If instead, you want the height of the collection view to stay the same, but move down (assuming that it's short enough that there's room to move down), give the collection view a fixed height constraint, and remove its constraint to the bottom of the view.

Change size of window in Cocoa?

I have a window whose size I need to change when the user clicks on it. I am using [self setFrame:windowFrame display:YES animate:YES] to accomplish this.
Even though the window successfully changes size (I increase its height), it moves the contents of the window up with it. How do I prevent this from happening? I want the contents to remain in place.
I am on OSX Mountain Lion developing an app for OSX using Objective-C and Cocoa.
EDIT: Constraints and/or Springs and Struts will not work as I need to move the contents around after the window is resized.
Constraints and/or Springs and Struts will not work as I need to move the contents around after the window is resized.
In that case, you should use NSViewAnimation.
A single view animation can actually perform multiple animations to multiple views, and you can even do one to a window, despite the class's name and the fact that windows aren't views in Cocoa.
You create a view animation with initWithViewAnimations:, which takes an array of dictionaries. Each dictionary identifies the target (NSViewAnimationTargetKey) and what to do to it: Either change the target's frame (NSViewAnimationStartFrameKey and NSViewAnimationEndFrameKey) or fade the target in or out (NSViewAnimationEffectKey). For your case, you'll be changing the targets' frames.
When the user does the thing that causes the resize of the window, you'll need to compute the desired overall size of the window (taking care to adjust its frame's position so it doesn't grow off the screen), as well as the new frames—both positions and sizes—of your views. Everything that will move and/or change size, create a dictionary for it and throw it into the array. Then create the view animation.
An NSViewAnimation is a kind of NSAnimation, which provides all the methods for starting and stopping the animation, monitoring its progress, hooking into it, and chaining multiple NSAnimations together. If nothing else, you'll need to start the animation.
If you are using the Interface Builder to build these views, then I believe one approach is to set the "struts and springs." These are available under the "size inspector" and are the red arrows and bars above the "autosizing" label. Play around with these to get the effect that you want, but the general idea is that the arrows control how the size of the view adjusts to changes in the size of the parent view, and the bars control the relationship of the edges of the view to the edges of the parent view as the size changes.
In constraint-based layout, set the views around the edge of your window to be a fixed distance from their superview's edge.
Xcode will infer a lot of resizability from that; if anything still isn't resizing properly, adjust its constraints so that its width and/or height is no longer constant.
The easiest way is to move your views until blue lines show up in the editor. Each blue line corresponds to a rule in the HIG about how things should be lain out, and if you drop the view there, Xcode will create constraints matching those guidelines. For example, if you set a view 20 points from the right edge of its superview, you'll get a blue line for that, and if you drop the view there, you'll create a constraint that the view must remain that distance from that edge.
The superview isn't the only view with which you can create HIG-based constraints. You can also create guideline constraints between sibling views. For example, if you put a button next to another button at the appropriate distance, you'll get a blue line across that distance, and if you drop it, you'll create a constraint that those two buttons must remain that distance from each other.
If you want to do something really custom, the three buttons in the lower-right corner of the nib editor will let you create any constraint you want. What you have selected determines what constraints you can create; the nib editor's outline view will help you make sure you have the selection you want.
You are going to have to iterate through all of your subviews and change their frame positions based on the delta of your window frame.
so if you expand your window frame by 20 in all directions, all your subviews are going to have to increase their frame positions by (20,20) to offset the windows movement.