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

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

Related

ScrollView with embedded StackView issue

I have a scrollView with a stackView placed in it. The scrollView is constrained to the rootview. The stack view will show a xib view.
The xib views are all different lengths.
The xib views are labeled simpleVC0 and simpleVC1. The length of the simpleVC0is 2500 and the length of simpleVC1 is 1000.
My problem is that when the xib views are presented in the stack view the length of the scrollView does not change to the length of the presented xib view.
It is like the xib view is presented but the scroll view is locked at a specific length.
Here is simpleVC0 xib view. followed by it when run. When I try to scroll it doesn't allow me to scroll to the bottom of the xib view. it seems to cut the xib view off at a certain length.
Am right in saying that this is possibly an issue that may have to be resolved in code? or can it it solved souled by the constraints.
I have tried auto layout constraints however they have not worked.
I have constrained the scrollView to the rootview on all four sides.
When the root view is loaded the xibs are established using the following code:
//Different subViews for ingredients and steps
if counter == 0 {
simpleViewX = SimpleVC0().view
simpleViewY = SimpleVC1().view
stack.addArrangedSubview(simpleViewX)
stack.addArrangedSubview(simpleViewY)
}
The views are the hidden shown by changing the value of the segmented view controller. Shown below:
#IBAction func tabselected(_ sender: Any) {
switch (sender as AnyObject).selectedSegmentIndex {
case 0:
simpleViewY.isHidden = true
simpleViewX.isHidden = false
break
case 1:
simpleViewX.isHidden = true
simpleViewY.isHidden = false
break
case 2:
//calledvideo in array is the value of the counter.
calledVideo = vids[counter]
geturl()
break
default:
break
}
}
To use a UIStackView with a UIScrollView you need to allow the stack view to expand its height based on its content.
When laying it out in storyboard, give the stack view a height constraint (to satisfy IB's requirements), but give that height constraint a low Priority.
Then, when adding arranged subviews, the stack view will grow vertically.
Here's a complete example, based on the images you've shown: https://github.com/DonMag/XIBsInScrollView
You have to modify the contentSize property of your scrollView in the code. I don’t know how to deal with it with storyboards, but you can make an outlet of your scrollView and calculate the new height each times it changes (each time you add something or remove something in it)
scrollView.contentSize = CGSize(width:yourNewW, height:yourNewH)

Dynamic NSStackView that resizes to fit its content

I want to use an NSStackView as "floating" container for buttons. i.e. a horizontal NSStackView that acts as toolbar of sorts and contains a row of square buttons (with fixed size). In runtime, some buttons will be dynamically shown/hidden and I want this NSStackView to dynamically adjust its width according to the visible buttons (plus spacing, edges, etc).
So, this NSStackView would have:
Fixed height
Dynamic width based on its content
Its exact position in parent view is not known in design time
A row of NSButtons with fix sizes
I have a nib file that contains the NSStackView and its buttons, which I load in runtime:
Bundle.main.loadNibNamed("ToolbarView", owner: self, topLevelObjects: nil)
toolbarView.detachesHiddenViews = true
toolbarView.setFrameOrigin(NSPoint(x: 100, y: 100))
I am struggling to find the exact combination of properties and constraints to make this behavior work. When I hide some buttons, the NSStackView detaches them but doesn't shrink to fit the shown buttons total width. I tried all NSStackView NSStackViewDistribution options.
I suspect I'm missing some constrains to make this work but all the NSStackView examples I find anchor the NSStackView to it's superview and I can't do that because its position in parent view is set in runtime.
Is there any way to make this work or do I need to fall back to manually calculating width from the visible buttons (which kind of makes using NSStackView pointless)?
What is the value of translatesAutoresizingMaskIntoConstraints on the stack view after loading it from the nib? If true, what is the autoresizingMask? (the default it should be .none).
If that is the case, then there are autoresizing mask constraints that hold the stack view's frame origin and size in place (i.e whatever gets loaded from the nib).
The best way to deal with this is to set translatesAutoresizingMaskIntoConstraints to false and then use constraints to position it in its parent view at runtime.
In addition to the already-mentioned translatesAutoresizingMaskIntoConstraints and leading and top constraints, have you tried modifying the stack view's hugging priority? Use a value of 1000 (required) to absolutely prevent the stack view from extending beyond its contents:
stackView.setHuggingPriority(1000, for: .horizontal)

NSSplitView with Autolayout, prevent proportional resize

I'am using autolayout with NSSpliView, the setup is as following on the picture
The split view is in a window which can resize, when it resizes, the divider is changing proportional 50:50, how to change this, so that the height of the bottom view stays and the top view gets resized (but no more than 124px) but still have the freedom also to change it manually by dragging the split?
So just to recap you have three requirements,
Bottom view stays the same size on resize
Reduce the holding priority if the top view (select the NSSplitView to get the correct inspector)
Top view cannot resize more than 124px
Add a inequality constraint which sets the height of the view to less than or equal to 124px. You can do this in IB. It will also be a good idea to create a IBOutlet for this constraint in your custom view of controller class for the next step...
When the divider is moved the top view should be able to get smaller than 124px.
I not entirely sure but checkout the NSSplitView delegate method such as splitView:resizeSubviewsWithOldSize: or splitViewDidResizeSubviews:. When you resize with the divider the delegate method should override the height constraint to be the current resized size. So something like the following in the delegate method
self.heightConstant.constant = NSHeight(topView)
Or you could just remove the constraint and re-add it later when needed.

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.

How to stop interface builder resetting user constraints on UIScrollView?

I'm having trouble getting a UIScrollView to respect the constraints I put in interface builder.
All I need to be able to do is set the content size of the scroll view from within IB.
The UIScrollView contains a single UIView.
Constraints on the UIScrollView:
Constraints on the UIView:
I've read through the documentation, and so have set things up as follows:
the UIScrollView has constraints pinning it to its superview, thus defining its size from outside
the UIView (content) has a fixed size (through width and height constraints)
the UIView is pinned to the UIScrollView, thus defining the content size
However, IB won't let me enter these constraints. If I change the 'Bottom Space' constraint between the view and the scroll view, shown in the image as -2196, to 0 (thus pinning the lower edge of the scroll view), then the 'Top Space' constraint resets to a non-zero value. The same happens in reverse. (I haven't yet tried in Xcode 5, which has a far saner approach to invalid constraints in that it doesn't just throw yours away when it feels like it.)
What am I missing?
Every time I've tried to do something even mildly sophisticated with constraints in Xcode 4's Interface Builder, I've eventually given up and either written the constraints in code or switched back to springs'n'struts and layoutSubviews (usually after crashing Xcode a few times).
That said, there is another approach to laying out a scroll view with content in IB. Just make the scroll view as big as its content size, and rely on the view controller (or some containing view controller) to resize the scroll view (or its superview) and let the constraints shrink down the scroll view's frame at runtime. The window's root view controller will always set its view's frame to the screen size, regardless of its size in the nib or storyboard, and that resizing flows down the view hierarchy.
I described this approach in more detail in this answer.
If your scroll view's content size is really supposed to be 2196 points tall, this probably won't work so well. I don't have anything better to suggest in that case.

Resources