It's a common technique to wrap content in a UIScrollView for the purpose of moving it out of the way when a keyboard appears. This is done by modifying the frame/bounds of the scroll view, so that it encompasses the area not covered by the keyboard. According to Ole Begemann, one shouldn't use the frame property when using autolayout.
How does one accomplish this same effect without using frame?
You can create an outlet to your constraint(s) in IB, e.g. to the constraint that connects the bottom of the UISCrollView to the superview, and then use code to change the constant of that constraint. This can also be animated in an animation block.
self.someConstraint.constant = ...;
Related
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.
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 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.
I'm trying to scroll the contents of a UIView using the contentOffset which so far I achieve handling touchesBegan: and touchesMoves: methods of the view, however I get a jumpy effect as I'm changing the bounds of the UIView manually (for example: current position +/- the change of the last position of the finger and the new position)
Is there any easy way to achieve this without manually changing the bounds of the UIView?
IMPORTANT NOTES: I'm not using a UIScrollView because the mentioned UIView has plenty of draggable subviews so if I use a UIScrollView I can't drag because the UIViewScroll scrolling event executes over the subviews events.
Animating the layer of the mentioned UIView causes the contents to move out of control, like if the point of reference had changed somehow.
However I'm always open to suggestions.
I would rather make a UIView container clipping subviews, add the content view which we will drag as a subview and change it's frame. I think it shouldn't have jumpy effect as it must be the same as animating the view frame change.
I'm trying to create a little slider mechanism which operates as a box/view with a static line image in the center and behind it are pins. The pins look like marks on a ruler. When you slide the marks to the left or right; they keep coming continuously (a loop). And I need to use this as a controller of a view, like a selector. All it needs to do is scroll through a list when the pins are slid. How can I put this together?
Create a UIView and add a UISwipeGestureRecogniser to it. When the swipe occurs update a ivar and either redraw or animate a bunch of repeating UIimageView subviews.
The latter will be preferable for efficiency and smoothness.