views:

1370

answers:

3

I'm having a hard time getting this right.

I've got a UIScrollView, with paging enabled. It is managed by a view controller (MainViewController) and each page is managed by a PageViewController, its view added as a subview of the scrollView at the proper offset. Scrolling is left-right, for standard orientation iPhone app. Works well. Basically exactly like the sample provided by Apple and also like the Weather app provided with the iPhone.

However, when I try to support other orientations, things don't work very well. I've supported every orientation in both MainViewController and PageViewController with this method:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
     return YES;
}

However, when I rotate the device, my pages become quite skewed, and there are lots of drawing glitches, especially if only some of the pages have been loaded, then I rotate, then scroll more, etc... Very messy.

I've told my views to support auto-resizing with

 theView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

But to no avail. It seems to just stretch and distort my views.

In my MainViewController, I added this line in an attempt to resize all my pages' views:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * ([self.viewControllers count]), self.scrollView.frame.size.height);

for (int i = 0; i < [self.viewControllers count]; i++) {
    PageViewController *controller = [self.viewControllers objectAtIndex:i];
    if ((NSNull *)controller == [NSNull null])
        continue;

    NSLog(@"Changing frame: %d", i);
    CGRect frame = self.scrollView.frame;
    frame.origin.x = frame.size.width * i;
    frame.origin.y = 0;
    controller.view.frame = frame;
}

}

But it didn't help too much (because I lazily load the views, so not all of them are necessarily loaded when this executes).

Is there any way to solve this problem?

+1  A: 

I'm not absolutely sure I understand you right.. however, some thoughts:

The frame property is one thing (A), how the view contents are displayed in there is another (B). The frame CGRect is the (theoretical) boundary of your view in the superview (parent view) .. however, your View does not necessarily need to fill that whole frame area.

Regarding (A): Here we have the UIView's autoresizingMask property to set how the frame is resized when the superview is resized. Which happens when you change the orientation. However, you can usually rely on the default settings (worked for me so far).

Regarding (B): How the view contents are distributet in the view frame is specified by UIView's property contentMode. With this property, you can set that the aspect ratio needs to stay intact. Set it to UIViewContentModeScaleAspectFit for example, or something else..

see here: http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816-CH3-SW99

PS: I wrote "theoretical", because your view contents may also exceed those frame boundaries - they are only limiting the view when UIView's clipsToBounds property is set to YES. I think it's a mistake that Apple set this to NO by default.

Efrain
+1  A: 

In addition to what Efrain wrote, note that the frame property IS NOT VALID if the view transform is other than the identity transform -- i.e., when the view is rotated.

Of course, you accounted for the fact that your views need to be at a new offset position, right?

Olie
The frame property is valid on an view when its OWN transform is the identity. The autorotation stuff uses a transform at a deeper level (maybe the window)-- a scroll view sitting on the window that doesn't actually alter its own transform can use the frame property with no problem. OP doesn't appear to be changing the explicit transform on his/her scrollview.
quixoto
+1  A: 

If I understand your question correctly, the answer is given in this excellent WWDC presentation: https://deimos.apple.com/WebObjects/Core.woa/BrowsePrivately/adc.apple.com.4092349126.04109539109.4144345585?i=1699219987 (Note that you have to be a registered iPhone developer to access these videos).

By the way, is it necessary to have a separate UIViewController (PageViewController) for every page in your UIScrollView? Why not let your MainViewController take care of this.

Resizing your views (and your UI in general) after rotating the device is much easier when you build your UI in Interface Builder.

Once again, I recommend the WWDC session linked above as it helped me quite a bit with paged scroll views and how to handle rotation.

Best of luck!

bare_nature
I've seen that session video, and while it is educational, it doesn't handle rotation at all. I've since fixed my problem, mostly, but haven't posted the solution here as it's convoluted and I just don't have the time.
jbrennan