Tuesday 23 August 2011

UIPageControl Tutorial


You have to make two view Controllers
First :- That will contain your scrolling and deegate implementation.
Second:-That will describe what you want to show in your view.

the first file should be the same and you might do changes in your second file depending on your layout requirements.

First:-
In your .h file (MyCardsViewController.h)

#import <UIKit/UIKit.h>


@interface MyCardsViewController : UIViewController <UIScrollViewDelegate>{

UIScrollView *scrollView;
IBOutlet UIPageControl *pageControl;
NSMutableArray *viewControllers;

// To be used when scrolls originate from the UIPageControl
BOOL pageControlUsed;
}

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

- (IBAction)changePage:(id)sender;

@end

In your .m file (MyCardsViewController.m)

#import "MyCardsViewController.h"
#import "MyViewController.h"

static NSUInteger kNumberOfPages = 3;

@interface MyCardsViewController (PrivateMethods)

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

@end


@implementation MyCardsViewController
@synthesize scrollView, viewControllers,pageControl;


/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
*/
- (void)viewDidLoad {
self.navigationController.navigationBar.hidden=YES;
[super viewDidLoad];

// 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 = 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;

// replace the placeholder if necessary
MyViewController *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null]) {
controller = [[MyViewController alloc] initWithPageNumber:page];
[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 - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];

// A possible optimization would be to unload the views+controllers which are no longer visible
}

// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (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 {
self.pageControl=nil;
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}


- (void)dealloc {
[pageControl release];
[viewControllers release];
[scrollView release];
[pageControl release];
[super dealloc];
}

@end

in your this viewController xib add a scrollview and a page control and bind it.

Start up with secondViewController

in .h file:-

int pageNumber;
UIImageView *imageView;
}


@property(nonatomic,retain) IBOutlet UIImageView *imageView;

- (id)initWithPageNumber:(int)page;

in .m file

+ (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 {
if (self = [super initWithNibName:@"MyViewController" bundle:nil]) {
pageNumber = page;
}
return self;
}

- (void)dealloc {
[imageView release];
[super dealloc];
}

// Set the label and background color when the view has finished loading.
- (void)viewDidLoad {
[imageView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"cardview%d",pageNumber + 1]]];
self.view.backgroundColor = [MyViewController pageControlColorWithIndex:pageNumber];
}

1 comment:

  1. This isn't by far a tutorial. Is a bad formatted code dump of something very poorly documented on the top.

    ReplyDelete