iOS Uniform scale subviews with superview - iphone

I have an app that allows a user to drag views onto the screen in multiple orientations. So lets say i'm in portrait mode and my superview is 768x1024. Lets say I drag 10 different items onto that superview. These items are scaled, rotated, etc. Then I rotate the device and my superview shrinks down to 576x768. How do I get all of my subviews to maintain their position and transform relative to the new smaller size? So in essence my superview and all of its subviews should look exactly as they did while in portrait, except everything has been scaled down.
And also, what if im in landscape and everything is "shrunk" down and then I drag another view on and shrink it down to fit well. I would need that new view to scale up in proper place and size when the device is rotated back into portrait

The easiest thing to do here is to use the transform property of your view. In this case, you'd prevent the view from auto-resizing on rotation, and use something like your view controller's willAnimateRotationToInterfaceOrientation:duration: method to set a transform on your superview. You can create a transform with CGAffineTransformMakeScale that will scale up or down all of your content; you'll probably want one for landscape and just use a nil transform for portrait (or vice-versa).
This will complicate dragging new views into your superview, since it's transformed, but once you've got views in there, they should behave correctly when resizing. For new views, you'll have to compute (perhaps using convertRect:fromView: method of UIView) what a rect will be once you add a new subview.

You can also override your view's layoutSubviews() directly and assign your subview's transforms based on your view's dimension. This way, you can still get the benefits of using Auto Layout with your view and potentially other sibling UI items, while you customize subview's frames and/or transforms manually without Auto Layout.

Related

How to determine the frame of a view after an iPhone is rotated, before the rotation actually takes place

I'm currently dealing with an iphone view controller which contains a paging UIScrollView, to display multiple pages of information. My application needs to support a landscape mode, and I've been having a bit of trouble figuring out the right way to implement this.
In order to maintain view continuity, I want to resize my views manually in two steps. First, I override willRotateToInterfaceOrientation. In this method I extend the width of all my views in the paging scroll view to the width that they'll end up at in landscape mode. Then, in didRotateToInterfaceOrientation, I reduce the height of the views to fit the height of the landscape mode.
My question is, how do I determine the new width and height to resize my views? Hardcoding the exact values feels like a bad hack, and I get the sense that there must be an elegant way of solving the problem.
I'm not sure why you're doing layout in didRotateToInterfaceOrientation:, which happens at the end of the rotation. In any case, the new frame should already be set by UIViewController.
If you're going to sync things to the animation, look at willAnimateRotationToInterfaceOrientation:duration:. According to the docs,
This method is called from within the animation block that is used to rotate the view. You can override this method and use it to configure additional animations that should occur during the view rotation. For example, you could use it to adjust the zoom level of your content, change the scroller position, or modify other animatable properties of your view.
By the time this method is called, the interfaceOrientation property is already set to the new orientation. Thus, you can perform any additional layout required by your views in this method.

trouble with rotating view (and resizing elements within) in ipad application

I'm having a nightmare with the rotation on iPad. I've searched all over the place for some tutorials, but nothing seems to really be for what I want. (Possibly not searching for the right thing?!)
I have a portrait view by default which is an image and a button inside the view. When I rotate, I detect this can work out if it's landscape. I then try to set the frame size of the uiview to fit nicely on the screen.
If I let it autoresize, it simply stretches and fills the screen. This I don't want.
but the trouble is, when I resize, the button gets resized too, but not in the same ratio as the image.
My question is: What's the best way to resize the view. I wanted to simply reduce the uiview by say 60% and it resizes EVERYTHING in that view with the same 60%. The only way I see this is working at the moment is to create two views... but that's twice the work and maintenance!
I've tried messing with the autosizing arrows in Interface builder, but that again seems to screw things up more!
I'm completely lost here!! Thanks for any info
The problem you have there is that the view is automatically resized to the screen ratio. On an iPad in Portrait Orientation the screen size is 1024x768. After the rotation to Landscape the origin rotates too and your screen content is skewed or stretched to 768x1024.
What you need to do is to override the
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
message of the UIViewController of the view which rotates. This message is called within the animation block of the rotation. You just set the framesize of your subviews (the button) to whatever is best for you. Once i had a problem with rotating an OpenGL view. The content of the view was stretched when rotating to landscape. Since it is not possible to alter any OpenGL matrices within the animation block the only solution i found was to make the view quadratic and to set the origin behind the bounds of the screen (in -x direction). You have to override the message also to reset the origin above the screen (in -y direction) bounds in landscape mode, to keep the viewport in the middle of the screen. That way the view kept its ratio. Whatever solution is best for you, overriding this message should work out.
Have you tried disabling the autoresizesSubviews property on your UIView? It should prevent any size changes on the subviews when you resize your view.

preventing a specific view from auto rotating... is that possible?

I have a view based app. Its self.view has several subviews and shouldAutorotateToInterfaceOrientation is returning YES.
When I rotate the device, all views rotate as expected.
Is that possible to prevent a subview from auto rotating even if the view's parent is auto rotating?
Keep in mind that it's the view controller that controls what happens during rotation and not the view itself. You can't stop a subview from rotating by setting a property, or something relatively easy, if its parent view's UIViewController is set to auto rotate. You can, however, have sibling views where one rotates and the other doesn't. It's probably possible to layout your views the way you want but not have the one that shouldn't rotate as a subview of a rotating UIViewController.
You could probably write some code that will reorient a subview so it appears not to rotate when the parent view does rotate, however.

UIView scaled to thumbprint, what about subviews?

I have a UIImageView that I create progmatically right? Works like a charm when I initWithImage and set the parameters for scaling to UIViewContentModeScaleToFill. I can scale all day long and create many different smaller 'thumbprint' sized versions of the UIImageView at whim, HOWEVER when I add subviews to said UIImageView and then try to scale the happy new parent the child subview does not scale! I looked around and found that I should enable the setAutoresizingSubviews boolean of the parentView to true (Which I did) and then call:
ChildView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
Which I also did... now when I scale the parent view the child also scales but crazy wacked out like and goes all over the place (Not a very good way of putting it) but my point is that I assumed the child would scale proportionally to the parent and stay in the same place (Which it doesn't)
My question is how do I set up my code so that when I scale my parent view by 1/4 or w/e to make a thumbprint of the view the children subviews that the parent view owns will scale accordingly and allow the 1/4 sized thumbprint to look just like the full sized view (Just smaller).
To scale subviews, you need to set the affine transform of the view to scale the contents instead of using the content mode.
The autoresizing mask isn't for scaling subviews. Instead, it's a springs-and-struts model for how to position and resize the frame of subviews when the parent view is resized. Mostly it's used when the view autorotates from landscape to portrait and vice-versa.
What you're trying to do is scale the content of the view. So instead of using UIImageView, which is optimized for displaying images, I would create a custom subclass of UIView, and then in the initialization, set the view's transform with this code:
self.transform = CATransform3DMakeScale(zoom, zoom, 1.0f);
Then put the subviews in. You can re-set the transform and the subviews will stay in the same positions relative to each other, but at a different scale.

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.