Thursday, July 1, 2010

Page controller with scroll view (first xib in another xib)

outer.h

@interface outer : UIViewController {

NSInteger kNumberOfPages;
NSInteger selectedPage;
NSArray* arrRepList;

IBOutlet UIPageControl* pageControl;
IBOutlet UIScrollView* scrollView;

NSMutableArray *viewControllers;
//BOOL pageControlUsed;
}

@property (nonatomic, retain) UIScrollView *scrollView;
@property (nonatomic, retain) UIPageControl *pageControl;
@property (nonatomic, retain) NSMutableArray *viewControllers;

- (IBAction)changePage:(id)sender;

@end


outer.m

@interface outer (PrivateMethods)

- (void)loadScrollViewWithPage:(int)page;
- (void)scrollViewDidScroll:(UIScrollView *)sender;

@end

@implementation outer

- (void)viewDidLoad {
[super viewDidLoad];
kNumberOfPages = 7;
self.title = @"Outer XIB";

// view controllers are created lazily
// in the meantime, load the array with placeholders which will be replaced on demand
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 = selectedPage;
[pageControl setFrame:CGRectMake(pageControl.frame.origin.x,pageControl.frame.origin.y,pageControl.frame.size.width,pageControl.frame.size.height*(3.0/4.0))];
//CGRect tmp=CGRectMake(320*selectedPage, 0,320,305 );
//[scrollView scrollRectToVisible:tmp animated:YES];
[self changePage:nil];

}

- (void)loadScrollViewWithPage:(int)page {
if (page < 0) return;
if (page >= kNumberOfPages) return;

// replace the placeholder if necessary
UIRepDetailsViewController *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null]) {
controller = [[UIRepDetailsSubView alloc] initWithPageNumber:page andRepList:arrRepList];
[viewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}

// add the controller's view to the scroll view
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 {
// We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
// which a scroll event generated from the user hitting the page control triggers updates from
// the delegate method. We use a boolean to disable the delegate logic when the page control is used.
/*if (pageControlUsed) {
// do nothing - the scroll was initiated from the page control, not the user dragging
return;
}*/
// Switch the indicator when more than 50% of the previous/next page is visible
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 - 2];
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
[self loadScrollViewWithPage:page + 2];
// A possible optimization would be to unload the views+controllers which are no longer visible
}

// 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 - 2];
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
[self loadScrollViewWithPage:page + 2];
// 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;
}





inner.h

/* all declarations */
int pageNumber;
NSArray* arrRepList;

inner.m

static NSArray *__pageControlColorList = nil;

@implementation inner

// Creates the color list the first time this method is invoked. Returns one color object from the list.
+ (UIColor *)pageControlColorWithIndex:(NSUInteger)index {
if (__pageControlColorList == nil) {
__pageControlColorList = [[NSArray alloc] initWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor magentaColor],
[UIColor blueColor], [UIColor orangeColor], [UIColor brownColor], [UIColor grayColor], nil];
}
// Mod the index by the list length to ensure access remains in bounds.
return [__pageControlColorList objectAtIndex:index % [__pageControlColorList count]];
}

// Load the view nib and initialize the pageNumber ivar.
- (id)initWithPageNumber:(int)page andRepList:(NSArray*) repList{
if (self = [super initWithNibName:@"RepDetailsSubView" bundle:nil]) {
pageNumber = page;
arrRepList = repList;
}
return self;
}

No comments:

Post a Comment