UIScrollView Using Only Interface Builder - objective-c

I know this question has been answered before, many times, but my use case seems to be just different enough from all of them that I can't quite figure it out.
My Problem
I have a scroll view that is not the same size as its superview. The scroll view has 1 subview that is the same size as it, but it needs to be able to be pinch-zoomed.
Attempted Tutorials:
(1) - Apple's Technical Note - This is done only with code and the examples show only full screen scroll views.
(2) - Natasha The Robot's Article - This was a really well written article but I could not get it to work for me. I think it's due to the fact that her scroll view is full screen.
(3) - Happy Coding Blog Article - Another full screen scroll view
... and lots other tutorials that were very similar to these
My requirements
My scroll view needs to be full width
My scroll view needs to be 40pt from the top and have a 1:1 aspect ratio
My scroll view needs to have one subview that is the exact same size of it but can be pinch-zoomed (aka content size = scroll view size)
I don't think that the size of the scroll view should impact anything, but it appears to.
What I have tried
As all the tutorials above recommended, I have only a single subview of the scroll view and have aptly named it "Content View".
View Controller
|-View
|-ScrollView
|-ContentView
|-ZoomableView
Here is a picture of my constraints:
As you can see, I have an equal width set up from the "Grid" (Zoomable view) to the view controller's view. I've also tried adding an equal width of the content view and the VC's view.
My question
I know I can get this to work with an explicit width and height, but I know I should be able to get it by setting the width equal to the view's width and height equal to the view's width as well (AKA 1:1 aspect ratio). How can I achieve this?

I think I ran into the same problem in the past. What I end up doing was adding a "container" view and use it to set up my width and height equality constraints instead of the view controller's view.
This setup will produce what you want I think: a scrollview with 1 subview that can be pinch-zoomed in the view controller's view (grey in the screenshot) but with a top margin of 40pt.

Related

Resizing superview that's an embedded UIViewController to fit subviews

Here's the scenario:
I have a segmented control that toggles between hiding/displaying two views that each embed a view controller (via use of the interface builder's provided "Container View"). For simplicity's sake, in each embedded view controller I have a single subview with fixed leading and trailing spacing to its superview's margins along with fixed top and bottom vertical spacing between the subview and its superview's top and bottom layout guides. If the superview (i.e. the embedded View Controller) is a fixed width and height, these constraints should fulfill the x-position, width, y-position, and height requirements (respectively).
Here's the problem:
I want to add a height constraint to the subview. If instead of embedding a view controller in the container view I had just placed the subview (with the added height constraint) inside a container view (that didn't have a fixed height constraint), the container view would be automatically resized to fit its subview. However, because the container view embeds a view controller, auto-layout doesn't consider the constraints set between View Controllers.
In other words, I want the "Container View" (or the embedded View Controller) to be resized in height according to the subview's height constraint.
Here's the type of solution that I'm looking for:
Ideally, I would like the solution to this problem to be as clean as possible, which in my eyes means:
1) Sticking with the interface builder and storyboarding.
2) IBOutlets for NSLayoutConstraints.
3) Subclassing if need be.
However, any working solution besides the one that I proposed (which was to not embed a View Controller) would help me out.

Autolayout: NSStackView won't resize parent view when height dynamically changed

Similar question: How to resize a parent view based on the size of subviews layouted with Autolayout
I got an NSStackView which loads DisclosureViewControllers (NSViewController subclasses) just like in the Apple Example InfoBarStackView.
Those can expand and retract views of arbitrary height.
I would like the parent view containing the NSStackView to resize its height according to the contents of the NSStackView. In the Apple example that works.
However, unfortunately, Apple is resizing a NSWindow and I am using a CCNStatusItem (CCNStatusItem Github), a view that attaches to the status item in the Apple menu bar. That window resizes to the contents of the NSStackView when it loads, but doesn't resize when the contents change.
When I expand a section, the content overflows and gets clipped on the bottom edge of the view.
I went through all the constraints and tried to reproduce it exactly, but couldn't get it to work. In the Apple example, they are adding everything programmatically, whereas I added a NSStackView in Interface Builder.
Here are the constraints of the NSStackView:
My question would be: What constraints do I have in the Interface Builder (with what priorities), so that the parent view (the window) resizes with the contents of the stack view dynamically?
Do I have to call some method of the view to make it work?
Please let me know if I missed to provide some necessary information.
UPDATE
The accepted answer was the right way to do it. Here's the result. My forked version of CCNStatusItem can be found at https://github.com/julianvogels/CCNStatusItem.git
When using auto layout constraints, you don't need to call a view method to cause this effect, but just make sure that:
the views inside the stack view have constraints that will cause them to grow
the container has constraints to the stack view that indicate the container should grow with the stack view
the container doesn't have any constraints that would prevent it from growing
The screenshots seem to indicate it's not the first -- the views are growing as expected. So it could be either the second or third. The screenshot from interface builder seems to show that the bottom StackView<>Container constraint is optional (it's dashed). Depending on what the priority actually is, that could be your problem. Based on the design you described, there should be no reason for that constraint to be non-required.
The problem is that CCNStatusItem is not auto-layout-compatible. It sets the content view of its window to an instance of one of its own view classes (CCNStatusItemWindowBackgroundView). Your view is a subview of that view.
When it creates and adds its view, it does not turn off translatesAutoresizingMaskIntoConstraints or use constraints to position it relative to its superview. That basically means it can't be forced to a different size by constraints.
Likewise, when it adds your view to the background view, it does not turn off translatesAutoresizingMaskIntoConstraints on your view nor does it set up constraints to relate your view to the background view.
Since you've got the source, you can make those changes.

iOS stretch image to full screen

I have a scroll view with a image view inside. I was wondering whether it's possible to have the image inside the image view be much smaller than the resolution of the screen, and somehow be able to stretch it to fit the screen.
Set contentMode on the UIImageView and change its size.
[UIImageView setContentMode:UIViewContentModeScaleToFill];
Check the docs for more informations regarding UIViewContentMode:
http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816-CH3-SW69
Sure, just change the bounds of the imageView.
Am I missing something here?
Your UIImageView is within an UIScrollView I understand?
That would work by adjusting the scroll view plus adusting the image view appropriately. However that is not advisable to do. You will get lost in small errors with annoying effects.
I'd suggest to add an additional UIView that can match the bounds of the screen.
Add that view to the underlying "view" object and use the bringSubviewToFront method.
You could as well make sure that this new UIView is the first subview of the most underlying view object. You could achieve that by manipulating the subviews array structure - which I do not recommend in general wihout having fully understood everythng about the view hierarchy.
You can as well achieve that by adding the additional view at first before adding any other view. (Within IB just make sure that the new view is the topmost in the tree, coming next to the view controllers "view".) And then make it hidden until you actually need it. Then you unhide it. When it is not needed anymore then hide it again and neither delete it nor erase it from its superview.

I can't understand UIScrollView behavior

I've read a lot of documentation but still don't really understand how that UIScrollView works.
I have an example where I use an UINavigationViewController with the status bar (little top bar with wifi, battery, etc., icons) and a navigation bar (with the "back" button).
As the first subview of the UINavigatioViewController's main view I have a UIScrollView. Inside it I have created several subviews that make it's contents size to be 500 points.
In the "viewDidLoad" method I set the scroll view's "contentSize" equals to 500. But it doens't completely scroll down to show the last subview.
I read that I should add some points to the "contentInset" because of the "bars". I don't really know why. Isn't the scroll view inside the main view that is correctly framed? Why does it need to take the "bars" into account?
Anyway, I read that it should be like 64 points (44 navigation bar + 20 status bar). But it doesn't work.
The "magic" number (at least for me) is 84 points. I must add that quantity to the content size (584) or use it as:
self.scrollView.contentInset=UIEdgeInsetsMake(0.0,0.0,84.0,0.0); // AT THE BOTTOM!!
I'm really confused about this. Could anyone give a hand on understanding it?
Thanks.
self.scrollView.contentInset=UIEdgeInsetsMake(0.0,0.0,84.0,0.0);
UPDATE
I have seen that because I made my ScrollView size bigger in Interface Builder in order to add new elements beyond the normal small visible size, it had a "frame" size near to 500 points.
I set it frame size to 416 (just to fit and cover all the visible space) and now with a content size of 500 points (without any additional inset values) it scrolls perfectly.
But I still don't understand the previous behavior...

Resizing an NSView smaller than its subviews?

Couldn't find anything on the net about this and wondered if anyone on SO has a solution.
I have an NSView with several subviews that are centered by removing the left and right anchor points. When I resize my view, programatically or with the mouse, to a smaller width than the subviews: it pushes them off center. Has anyone come across this before and do you have a solution?
EDIT: I want to be able to resize my view to a zero width. The reason being, the view is actually part of a split view and I have hooked up a button to 'collapse' it. When it collapses all of the subviews are pushed off-center and aren't re-centered when the view is resized, effectively un-collapsing it.
I have solved my problem now and thought I would share incase anyone comes across this issue in the future.
No amount of playing with autosizing options or view layouts in Interface Builder seemed to stop my subviews from getting moved off center. I did manage to find this link here and from this page, the advice:
Springs and struts, as currently
implemented, are really no good for
anything but keeping either one or
both sides of a view "stuck" to the
nearest edge. Any sort of centering
behavior, division of gained/lost area
between multiple views, etc. has to be
done by hand.
Based on this I overrode my view's setFrame: method and manually laid out my subviews using their setFrame: method. This works great and gives me the results I'm looking for.
There is the same issue using NSSplitView, resizing here one Subview to be smaller than the Subview Subviews makes sense,e.g. having small charts in the upper subview, and an rss reader in the lower subview.
If you want to show only the rss reader in the lower subview, you can "hide" the upper subview, but after resizing the upper subview the NSImageView are not layed out the same as in the beginning. Check this nib/xCode Project and the following screenshot to see this behaviour.
Only workaroung is to override the resize function to stop getting smaller.