How to auto rotate your own custom views? - iphone

I've learned that the best way to get graceful rotation is to set the auto rotation mask on the view that you want resize or move. This works fine if you're using SDK views like UILabel, but if you have your own custom view that uses the drawRect method it doesn't rotate as gracefully. In fact the only thing that happens is that it stretches whatever you drew in drawRect.
I've tried redrawing both before and after the rotation, but it doesn't give me that smooth rotation.
I looked at a UITextField auto rotating (flexible width) in slow motion and it follows the edge perfectly during the rotation. That is what I want my view to do, so how do I do that? My views jump to the right position either before or after the rotation.

The following line will make your UIView stretch the middle pixel only. If this is not your desired behavior I suggest you read the documentation for contentStretch to learn how to manipulate the values of the CGRect.
[self setContentStretch:CGRectMake(0.5, 0.5, 0.0, 0.0)];

I would guess that the UITextField you're looking at has at least three subviews, one displaying the left cap of the field's border, one displaying the right cap, and one displaying the middle, with autoresizing masks of "flexible right margin", "flexible left margin", and "flexible width", respectively. If you set up your custom view something like that, and make sure its autoresizesSubviews property is set to YES, then you should get the same smooth resize that the text field does.

Related

How to perform an interactive animation with Auto Layout in which you interpolate between different constraints?

I'd like to have an interactive animation where a view transitions from one set of constraints to another as the user drags up/down the screen. The background image should shrink vertically (easy), and the profile image should change from being horizontally and vertically aligned to the background image to being anchored to the top and left corners of the background image. Is this possible?
Yes, it is possible, and you can see this effect in the Avvo app, for example (in the lawyer profile screen). The trick here is to smoothly transition from one set of constraints to another.
Here's an outline of how to do this:
add a UIScrollView. Add the view you want to animate as a subview to the scroll view.
Make your view controller implement
UIScrollViewDelegate
In the delegate method
scrollViewDidScroll(_:), update the constraints' constants as
needed.
Also in that method, when contentOffset crosses a
threshold value, flip to a different set of constraints, by setting
their active property to true or false.
To keep the view (the headshot image, in my example), pinned to the top as you scroll, just continuously update its top spacing constraints based on the contentOffset.y value.
Achieving a perfectly smooth transition may take some trial and error, but it definitely can be done!
Here are the screenshots showing the transition as you scroll up:

Creating a bounding box for a View

Is there a way to a bounding box for a view so that its subviews cannot leave the view?
I currently have UIImageViews which I move around, scale, rotate etc and they are able to leave the view area.
How does one set the superview to bound/hold the subviews within it?
How else can this be done. I currently detect the origin of the image this works to the point that the image moves until it reaches this origin, when it does, the image is stuck.
I use gestureRecognizers and this origin technique only works for panning/moving an image.
Any suggestions?
If you want to stop a view's subviews from being drawn outside its borders, you need to set its clipsToBounds property to YES. (See the UIView class reference for details.)
If you want to stop your views from being in certain positions, don't move them there! It's your code that's putting them where you don't want them to be. If you're using a gesture recogniser, presumably you have a method that responds to gestures by adjusting the frame of a view - put some conditions on this movement that prevent it from happening when you don't want it.
When you write these conditions, bear in mind that a view's origin is relative to its superview. For example, say you have a view controller with a view that takes up the whole screen of the device, and inside that a box that starts at 0, 100, and inside that some squares and circles and squiggly shapes that the user can move around. If you examine containerBox.bounds.origin, you'll find that it's 0, 100, but if you want to put a square in the top left corner of the box, you need to get its frame and set the origin to 0, 0. Something to look out for.
I didn't follow your explanation of the 'origin technique'. If you paste your code, I might be able to help.

What is actually changing when we zoom out a subView inside a UIScrollView?

I have a subview inside a uiscrollview. Then I zoom it out. So it becomes bigger and allows me to scroll through it.
So what is actually changing here? ContentSize of UIScrollView?
If you are not manually responding to changes in the zoom scale (like I describe in this answer), the view that you return from the -viewForZoomingInScrollView: delegate method is simply having a scaling transform applied to it by the UIScrollView. The frame size of the view is not changing, it is just being graphically transformed (which is why you see blurriness at higher scale factors).
The content size of the scrollview remains logically the same. If you check the frame of the scroll view it remains the same.
I think all that is changing is the scaling of the CGLayers. When you zoom in, it shrinks the clipping region frame smaller but then scales the CGLayer transform upwards. In other words, all the logical elements are still present it is simply choosing to draw and display a different part of it.
In the iPhone Application Programming Guide they have a good explanation about the relationship between frames, clipping regions and various transforms on views.

Problem with autoresizing when iPhone is rotated

In my iPhone app, I have a view (let's call it RectangleView) within the content view that I'd like to scale, along with all its subviews, when the iPhone is rotated. So, when the phone is rotated from landscape to portrait mode, I'd like RectangleView (and all its subviews) to keep their original shape and position relative to each other, but just get smaller. I am using autoresizing on it and all its subviews in Interface Builder to try and do this.
Now here's the problem. When the phone is rotated, all of RectangleView's subviews scale and move relative to the entire content view, not relative their parent view (which is RectangleView). This is a problem because the content view is now a different shape (portrait) than it was before (landscape), and so all the elements on the screen are in the wrong places, when they should just be scaled down within RectangleView. And I am confused because some of these elements even move out of RectangleView, which I didn't even know was possible since they are supposed to be contained within RectangleView.
Can anyone explain what might be happening here, and how I can just scale RectangleView and all its subviews to retain their original shape and positions, but just on a smaller scale? Thanks in advance!
Are you sure that they are moving out of the RectangleView, and it isn't that the RectangleView is resizing and filling the content area? Also, I'm not sure if it makes a difference, but I found that I needed to call [view setNeedsDisplay] after rotation to make my custom view work properly.

My Quartz drawing on iPHone is clipped after rotation!

I'm drawing three rectangles, one of which falls off the end of the view, (i.e. the drawing is bigger than the current view bounds) so you don't see the right edge. This is good, but when the view is rotated, the right edge is still clipped, even though there's plenty of room to draw it. How can I get the view to redraw the full rectangle?
I've tried:
1) changing the frame and bounds rectangles to bigger
2) calling setNeedsLayout
3) calling setContentMode:UIViewContentModeRedraw;
4) calling [self.view setClipsToBounds:NO]
Trying a CGLayer is next, unless somebody suggests something else.
-Owen
Make sure your autoresizing mask on this layer is set properly in IB. If its not stretching the right way on rotation then the view will not take the new shape of the screen.