how to make expanding view with autolayout? - xcode

(I don't know english well). I have a question: can you show an example of my problem. I want to make expanding list. i.e. i have a controller view and when I click on one of strings there appears a list with data of this strong under it, and other string shift below.

You can achieve this with an additional(!) constraint for the height, by which you can set the view's height to zero:
Define this constraint in the storyboard (or code).
Create an outlet property to the constraint. This must be a strong property because of deactivating a constraint will remove it from the corresponding views.
Give this constraint the highest priority. Other constraints which influence the hight should have smaller priorities.
You can now hide and show the view by activating and deactivating the constraint.
Animation of the change can be done with UIKit animations:
UIView *theView = self.view; // Must be a parent of the animated view
self.heightConstraint.active = isHidden;
[UIView animateWithDuration:0.25 animations:^{
[theView layoutIfNeeded];
}

Related

Dynamically resize a XIB's root view to the size of its contents with Autolayout

I create a XIB in Xcode and add a simple view as a subview:
What I want to achieve is that the subview has a fixed size and the rootview automatically resizes to the size of that subview, leaving a margin of 20.0 around it:
So I add a fixed width and a fixed height constraint to the subview. Then I add the four constraints for the 20.0 margin:
As the superview does not have any constraints there should be neither ambiguity nor conflicting constraints: I would expect the superview to shrink down in order to match the constraints. However, Xcode complains:
These constraints would only be conflicting if the rootview had a fixed size and that appears to be the case. So my question is: How can I make the rootview of a XIB flexible so that it dynamically adjusts its size to match its contents?
(Is that even possible with Interface Builder?)
How can I make the rootview of a XIB flexible so that it dynamically
adjusts its size to match its contents?
Not possible Interface builder.
As the superview does not have any constraints there should be neither
ambiguity nor conflicting constraints
Its not just a super view. Its also an objet in nib. We define simulated size for such views. This could be used to silence the errors. But again these are just simulated.
Is this rootView a view controllers view ? If yes i don't understand why are you trying to fix its withd to 280 and height to 168.
If this view is a custom view that you are going to add to another 'parent' view. Then you should change you simulated size to with 280 and height 168, and when adding this as subview you need to add two more constraints to position this rootview in the 'parent' view.
I had a same issue. I have a view in xib, which had dynamic content and it needed to fit into other superviews. so here is the answer how I achieved that
First you need to
myViewFromXib.translatesAutoresizingMaskIntoConstraints = false to prevent translating autoresizing mask into constraints. Then add subview superViewForMyViewFromXib.addSubview(myViewFromXib). And just add your constraints to superview like this:
NSLayoutConstraint.activate([
(myViewFromXib.topAnchor.constraint(equalTo: superViewForMyViewFromXib.topAnchor, constant: 0))!,
(myViewFromXib.bottomAnchor.constraint(equalTo: superViewForMyViewFromXib.bottomAnchor, constant: 0))!,
(myViewFromXib.leadingAnchor.constraint(equalTo: superViewForMyViewFromXib.leadingAnchor, constant: 0))!,
(myViewFromXib.trailingAnchor.constraint(equalTo: superViewForMyViewFromXib.trailingAnchor, constant: 0))!
])
superViewForMyViewFromXib.setNeedsLayout()
You can do this by editing the xib manually, for example to set a height constraint (in my case it was an inequality to set the minimum height):
add a constraint to a subview for the height
open the xib as a text file
find the constraint you added (eg by Cmd-F'ing to the value of the height)
cut and paste it into the root view's constraint section
Open the xib in interface builder again
The constraint appears and you can edit it like normal.
OMG, I cant believe you accept that this is not possible and change your way , if this was not possible then Xib would be useless. please don't provide wrong info to others your question is well detail but answer is more than poor:
answer is more than easy :
subview.frame.size.height = rootView.frame.size.height
subview.frame.size.width = rootView.frame.size.width

How can I change the size of an NSView when autolayout is active?

I have a NSViewController with an attached view defined in a xib. Everything is done properly (at least I hope), so that when I change the height of the view, all the subviews stay properly organized.
I want to change the height of the view programmatically. Basically, one of the subviews of my view is an NSTextView and when there is a lot of text inside, I want to enlarge the view.
If I change the frame.size of the view, nothing happens, because of the auto layout I think.
Is there a standard way to change the height (or the width) of the view in such a context ?
EDIT :
I have added a constraint to the view : I "pined" its height.
Then, I have added this constraint as an IBOutlet property.
Thus, I can change the .constant value of the constraint.
Create a new constraint for the view : "pin" its height.
Register this constraint as an IBOutlet property.
You can access the constraint and .constant value of it to change the size of your view.

NSTableView will not compress

I'm seeing kind of a weird bug with NSTableView/NSOutlineView and auto layout.
When I add an NSOutlineView to my nib and run the app, it will get bigger as expected from the given constraints, but it will never get smaller than the size it was in the nib. It's like it has an invisible "greater than or equal" constraint on it.
I have tested a few variations, and it seems that both NSTableView and NSOutlineView (inside the automatic scroll view) behave this way, but a plain scroll view with no content does not.
Please see the NSTableColumn documentation which states
minWidth
Returns the table column’s minimum width.
(CGFloat) minWidth
Return Value
The minimum width of the table column, in points. The default value is 10.0.

How can I get an NSView to resize to fit the desired sizes of its subviews using Auto Layout?

I have a superview with three subviews. Two of those subviews are fixed in size and position within the superview, but the third can vary in size depending on its contents.
I have set up auto layout constraints to set the size and position of each of the sub views, but what I would like to happen is that when the contents of the third view change, the superview should resize to be able to display it fully.
I have implemented - (NSSize) intrinsicContentSize on that subview so that it returns the size it would like to be, but I can't work out how to add a constraint which will trigger the superview to resize.
Any ideas?
UPDATE:
I've got this working by adding constraints to the view like this:
sizeWidthConstraint = [[NSLayoutConstraint constraintsWithVisualFormat:#"H:[self(==viewWidth)]" options:0 metrics:metrics views:views] lastObject];
sizeHeightConstraint = [[NSLayoutConstraint constraintsWithVisualFormat:#"V:[self(==viewHeight)]" options:0 metrics:metrics views:views] lastObject];
where "viewWidth" and "viewHeight" are keys in the metrics dictionary with the desired values. In udpateConstraints I can then analyse the contents of my view and do this:
[sizeHeightConstraint setConstant: size.height];
[sizeWidthConstraint setConstant: size.width];
to set new values and the next layout will cause the view to be resized.
UPDATE in answer to panupan's question:
When you create a constraint in this way, you can put in what is essentially a variable name. In this case, those names are viewWidth and viewHeight. They're known as the constants of the constraint. You also pass in a dictionary, called the metrics, to the [NSLayoutConstrating constraintsWithVisualFormat:...] call that give values for those constants.
So, in this case, I start out with the default height and width for my view as the values for the metrics dictionary keys viewWidth and viewHeight. Later on, I use the setConstant: method to change those values. In the example above, size is a CGSize structure that I have calculated from the contents of the view (i.e. based on the sizes of its subviews) and I am using the width and height values to adjust the constants.
This doesn't achieve quite what I was after, in that it doesn't cause the size of my view to re-size automatically based on the intrinsic sizes of the subviews, but it does give me a way to re-size it manually.

How to disable resizing of the subview of NSSplitView in Interface Builder?

I've created in Interface Builder a NSSplitView with two subviews. I want the left-side view to have fixed width. I've tried to define autosizing rules for both subviews but the left subview still changes width on window resizing (split view fills up a window). May be that caused by NSSplitView's Autoresizes Subviews property? (I can't uncheck it). What can I do?
The best way I found to do this in Interface Builder:
Drop the NSSplitView on the window
Select the Custom View you want fixed
Go up to the Xcode menu and select Editor > Pin > Width
Adjust the Constant in the Attributes Inspector to the size that you want the panel to be fixed at
Of course, you can also add this layout constraint through code as suggested above if you're feeling adventurous.
The behavior that you want required some code that you can do on the NSSplitView's delegate. However, you can have the same result using BWToolKit.
I think it should work with a NSLayoutConstraint, I work at the moment on at :).
EDIT:
Maybe to provide more details on my answer based on the comment hayden. You can define a constraint either by code or in the the IB.
In the IB select your left subview and click on the constraint buttons in the lower right corner defining a width constraints. If you select this new constraint now you can setup the the width an say it should be equal and set the size you like.
The seconed way is to create in code a NSLayoutConstraint object, i do it like this (this is just an example, and define not a fix width).
// define for the view: Constraint and AutoresizingMask option
NSView *view = self.view;
[view setTranslatesAutoresizingMaskIntoConstraints:NO]; // disable AutoresizingMask
NSDictionary *views = NSDictionaryOfVariableBindings(view);
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"[view(>=140,<=220)]" options:0 metrics:nil views:views]];
In general you find documentation to this topic under the term Auto Layout. To use it you have to enable auto layout and this featuer replace the old autosizing functions. (therefore i disable autosizing mask in the code).
This feature is quit new and you can do complex stuff with it but i think I is worth to study.

Resources