Programmatically Linking UIPageControl to UIScrollView

IosXcodeUiscrollviewUipagecontrol

Ios Problem Overview


I am making a simple slideshow view within my app. I'd like to link my UIPageControl to my UIScrollView. This shouldn't be too difficult, but I haven't been able to find a simple solution anywhere. Below is my code.

HelpViewController.h

#import <UIKit/UIKit.h>

@interface HelpViewController : UIViewController{
}
@end

HelpViewController.m

#import "HelpViewController.h"

@interface HelpViewController ()

@end

@implementation HelpViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	CGRect scrollViewFrame = CGRectMake(0, 62, 320, 404);
    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:scrollViewFrame];
    [self.view addSubview:scrollView];
    CGSize scrollViewContentSize = CGSizeMake(640, 404);
    [scrollView setContentSize:scrollViewContentSize];
    UILabel *label  = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 50, 21)];
    [label setText:@"Hello"];
    [scrollView addSubview:label];
    [scrollView setPagingEnabled:YES];
    scrollView.showsHorizontalScrollIndicator = NO;
    UIPageControl *pageControl = [[UIPageControl alloc] init]; 
    pageControl.frame = CGRectMake(110,5,100,100); 
    pageControl.numberOfPages = 2; 
    pageControl.currentPage = 0; 
    [self.view addSubview:pageControl];
    pageControl.backgroundColor = [UIColor redColor];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

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

@end

Ios Solutions


Solution 1 - Ios

Maybe this works for you

Don't forget to set the UIScrollView's delegate = self (or wherever you have the selector below).

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat pageWidth = self.scrollView.frame.size.width; // you need to have a **iVar** with getter for scrollView
    float fractionalPage = self.scrollView.contentOffset.x / pageWidth;
    NSInteger page = lround(fractionalPage);
    self.pageControl.currentPage = page; // you need to have a **iVar** with getter for pageControl
}

For your code it then would be:

.h file

#import <UIKit/UIKit.h>

@interface HelpViewController : UIViewController{
}

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

.m file

#import "HelpViewController.h"

@interface HelpViewController ()

@end

@implementation HelpViewController
@synthesize scrollView=scrollView_;
@synthesize pageControl=pageControl_;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    CGRect scrollViewFrame = CGRectMake(0, 62, 320, 404);
    self.scrollView = [[[UIScrollView alloc] initWithFrame:scrollViewFrame] autorelease];
    self.scrollView.delegate = self;
    [self.view addSubview:self.scrollView];
    CGSize scrollViewContentSize = CGSizeMake(640, 404);
    [self.scrollView setContentSize:scrollViewContentSize];
    UILabel *label  = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 50, 21)];
    [label setText:@"Hello"];
    [self.scrollView addSubview:label];
    [self.scrollView setPagingEnabled:YES];
    self.scrollView.showsHorizontalScrollIndicator = NO;
    self.pageControl = [[[UIPageControl alloc] init] autorelease]; 
    self.pageControl.frame = CGRectMake(110,5,100,100); 
    self.pageControl.numberOfPages = 2; 
    self.pageControl.currentPage = 0; 
    [self.view addSubview:self.pageControl];
    pageControl.backgroundColor = [UIColor redColor];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

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

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        CGFloat pageWidth = self.scrollView.frame.size.width;
        float fractionalPage = self.scrollView.contentOffset.x / pageWidth;
        NSInteger page = lround(fractionalPage);
        self.pageControl.currentPage = page; 
    }


@end

Solution 2 - Ios

This is actually quite simple to setup. Firstly you need to create the scroll view and page control. Make sure you implement UIScrollViewDelegate in the interface of the class.

    UIScrollView * scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * 3, scrollView.frame.size.height);
    scrollView.delegate = self;
    
    UIPageControl * pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 90, scrollView.frame.size.width, 20)];
    pageControl.numberOfPages = scrollView.contentSize.width/scrollView.frame.size.width;
    [pageControl addTarget:self action:@selector(changePage:) forControlEvents:UIControlEventValueChanged];

Then you need to add the following two methods:

- (IBAction)changePage:(id)sender {
    CGFloat x = pageControl.currentPage * scrollView.frame.size.width;
    [scrollView setContentOffset:CGPointMake(x, 0) animated:YES];
}

-(void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView  {
    NSInteger pageNumber = roundf(scrollView.contentOffset.x / (scrollView.frame.size.width));
    pageControl.currentPage = pageNumber;
}

These methods add the required communication between the page control and the scroll view.

Solution 3 - Ios

Following code will work for Swift:

func addScrollView() {        
    let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
    let numberOfPages: CGFloat = 4
    scrollView.contentSize = CGSize(width: scrollView.frame.width * numberOfPages, height: scrollView.frame.height * numberOfPages)
    scrollView.delegate = self
    scrollView.isPagingEnabled = true
    
    let pageControl = UIPageControl(frame: CGRect(x: 0, y: scrollView.frame.height - 37, width: scrollView.frame.width, height: 37))
    pageControl.numberOfPages = Int(numberOfPages)
    pageControl.currentPage = 0
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let value = scrollView.contentOffset.x / scrollView.frame.size.width
    pageControl.currentPage = Int(round(value))
}

Solution 4 - Ios

to get exact page index without rounding off the value simply put the pagecontrol.currentpage in the scrollViewDidEndDecelerating delegate method of scroll view.This works for me!

Solution 5 - Ios

All these answers are great but I'd like to offer an alternative solution, using ReactiveCocoa!

The following code makes an assumption that you have a property called scrollView and one called pageControl.

[RACObserve(self.scrollView, contentOffset)
  subscribeNext:^(NSValue* value){
      CGPoint offset = [value CGPointValue];
      CGFloat fractional = offset.x/self.scrollView.width;
      [self.pageControl setCurrentPage:lroundf(fractional)];
  }];

All that's going on here is you're observing change on the contentOffset property of the scrollView and calculating the page index on every next event (i.e. every time the property value changes).

The only downside of this is that you have to unbox the CGPoint but on the upside there's no UIScrollViewDelegate code needed at all!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDan CarewView Question on Stackoverflow
Solution 1 - IosJonas SchnelliView Answer on Stackoverflow
Solution 2 - IosJames AndrewsView Answer on Stackoverflow
Solution 3 - IosBilalView Answer on Stackoverflow
Solution 4 - IosHarshit KView Answer on Stackoverflow
Solution 5 - IosbarndogView Answer on Stackoverflow