Paging viewcontrollers in Landscape mode
I have this code, modified version of Apple's PageScrollView sample. Here the differnce is that m using ViewControllers instead of UIView.
MyClass.h
@interface MyClass : UIViewController {
UIScrollView *scrollView;
UIPageControl *pageControl;
NSMutableArray *viewControllers;
BOOL pageControlUsed;
}
@property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
@property (nonatomic, retain) IBOutlet UIPageControl *pageControl;
@property (nonatomic, retain) NSMutableArray *viewControllers;
- (IBAction)changePage:(id)sender;
@end
MyClass.m
#import "MyClass.h"
#import "MyViewController.h"
#import "MyViewControllerZero.h"
#import "MyViewControllerOne.h"
#import "MyViewControllerTwo.h"
static NSUInteger kNumberOfPages = 3;
@interface MyClass (PrivateMethods)
- (void)loadScrollViewWithPage:(int)page;
- (void)scrollViewDidScroll:(UIScrollView *)sender;
@end
@implementation MyClass
@synthesize scrollView, pageControl, viewControllers;
/*
// The designated initializer. Override if you create the controller programmatically and want to pe开发者_如何学JAVArform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < kNumberOfPages; i++) {
[controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
[controllers release];
// a page is the width of the scroll view
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.scrollsToTop = NO;
scrollView.delegate = self;
pageControl.numberOfPages = kNumberOfPages;
pageControl.currentPage = 0;
// pages are created on demand
// load the visible page
// load the page on either side to avoid flashes when the user starts scrolling
[self loadScrollViewWithPage:0];
[self loadScrollViewWithPage:1];
}
- (void)loadScrollViewWithPage:(int)page {
// if (page < 0) return;
// if (page >= kNumberOfPages) return;
if(page==0)
{
MyViewControllerZero *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null])
{ controller = [[MyViewControllerZero alloc] init];
[viewControllers replaceObjectAtIndex:page withObject:controller];
if (nil == controller.view.superview) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];
}
}
}
if(page==1)
{
MyViewControllerOne *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null])
{ controller = [[MyViewControllerOne alloc] init];
[viewControllers replaceObjectAtIndex:page withObject:controller];
if (nil == controller.view.superview) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];
}
}
}
if(page==2)
{
MyViewControllerTwo *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null])
{ controller = [[MyViewControllerTwo alloc] init];
[viewControllers replaceObjectAtIndex:page withObject:controller];
if (nil == controller.view.superview) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];
}
}
}
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (pageControlUsed) {
return;
}
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
// A possible optimization would be to unload the views+controllers which are no longer visible
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return YES;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
pageControlUsed = NO;
}
// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
pageControlUsed = NO;
}
- (IBAction)changePage:(id)sender {
int page = pageControl.currentPage;
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
// update the scroll view to the appropriate page
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
[scrollView scrollRectToVisible:frame animated:YES];
// Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above.
pageControlUsed = YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[viewControllers release];
[scrollView release];
[pageControl release];
[super dealloc];
}
@end
The Above code works absolutely fine in the potrait mode. But when i change the orientation,the whole paging gets screwed up.. :((
please help me to resolve this problem..
Apple didn't design UIViewController to work at any point in a view hierarchy. The views that you're adding to your UIScrollView are managed by view controllers, but I think you'll find that the view controllers for those views don't receive rotation events.
You could try to manually forward all events from the scroll view's controller to the child view controllers, but I think you'll find that to be tedious and error prone. I'd suggest instead that you simply use a single view controller for the scroll view and its child views.
精彩评论