iphone - How can I change the color of pagination dots of UIPageControl?

ID : 20335

viewed : 7

Tags : iphoneiosuipagecontroliphone

Top 5 Answer for iphone - How can I change the color of pagination dots of UIPageControl?

vote vote

98

UPDATE:

This answer is 6 years old and very outdated, but it's still attracting votes and comments. Ever since iOS 6.0 you should be using the pageIndicatorTintColor and currentPageIndicatorTintColor properties on UIPageControl.

ORIGINAL ANSWER:

I ran into this problem today and decided to write my own simple replacement class.

It's a sublassed UIView that uses Core Graphics to render the dots in the colors you specify.

You use the exposed properties to customize and control it.

If you want to you can register a delegate object to get notifications when the user taps on one of the little page dots. If no delegate is registered then the view will not react to touch input.

It's completely fresh from the oven, but seems to work. Let me know if you run into any problems with it.

Future improvements:

  • Resize the dots to fit the current bounds if there are too many.
  • Don't redraw the entire view in drawRect:

Example use:

CGRect f = CGRectMake(0, 0, 320, 20);  PageControl *pageControl = [[[PageControl alloc] initWithFrame:f] autorelease]; pageControl.numberOfPages = 10; pageControl.currentPage = 5; pageControl.delegate = self; [self addSubview:pageControl]; 

Header file:

// //  PageControl.h // //  Replacement for UIPageControl because that one only supports white dots. // //  Created by Morten Heiberg <morten@heiberg.net> on November 1, 2010. //  #import <UIKit/UIKit.h>  @protocol PageControlDelegate;  @interface PageControl : UIView  { @private     NSInteger _currentPage;     NSInteger _numberOfPages;     UIColor *dotColorCurrentPage;     UIColor *dotColorOtherPage;     NSObject<PageControlDelegate> *delegate;     //If ARC use __unsafe_unretained id delegate; }  // Set these to control the PageControl. @property (nonatomic) NSInteger currentPage; @property (nonatomic) NSInteger numberOfPages;  // Customize these as well as the backgroundColor property. @property (nonatomic, retain) UIColor *dotColorCurrentPage; @property (nonatomic, retain) UIColor *dotColorOtherPage;  // Optional delegate for callbacks when user taps a page dot. @property (nonatomic, retain) NSObject<PageControlDelegate> *delegate;  @end  @protocol PageControlDelegate<NSObject> @optional - (void)pageControlPageDidChange:(PageControl *)pageControl; @end 

Implementation file:

// //  PageControl.m // //  Replacement for UIPageControl because that one only supports white dots. // //  Created by Morten Heiberg <morten@heiberg.net> on November 1, 2010. //  #import "PageControl.h"  // Tweak these or make them dynamic. #define kDotDiameter 7.0 #define kDotSpacer 7.0  @implementation PageControl  @synthesize dotColorCurrentPage; @synthesize dotColorOtherPage; @synthesize delegate;  - (NSInteger)currentPage {     return _currentPage; }  - (void)setCurrentPage:(NSInteger)page {     _currentPage = MIN(MAX(0, page), _numberOfPages-1);     [self setNeedsDisplay]; }  - (NSInteger)numberOfPages {     return _numberOfPages; }  - (void)setNumberOfPages:(NSInteger)pages {     _numberOfPages = MAX(0, pages);     _currentPage = MIN(MAX(0, _currentPage), _numberOfPages-1);     [self setNeedsDisplay]; }      - (id)initWithFrame:(CGRect)frame {     if ((self = [super initWithFrame:frame]))     {         // Default colors.         self.backgroundColor = [UIColor clearColor];         self.dotColorCurrentPage = [UIColor blackColor];         self.dotColorOtherPage = [UIColor lightGrayColor];          UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedRight:)];         [swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];         [self addGestureRecognizer:swipeRight];             UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedLeft:)];         [swipe setDirection:UISwipeGestureRecognizerDirectionLeft];         [self addGestureRecognizer:swipe];      }     return self; } -(void) swipedLeft:(UISwipeGestureRecognizer *) recognizer {     self.currentPage++; } -(void) swipedRight:(UISwipeGestureRecognizer *) recognizer {     self.currentPage--; }  - (void)drawRect:(CGRect)rect  {     CGContextRef context = UIGraphicsGetCurrentContext();        CGContextSetAllowsAntialiasing(context, true);      CGRect currentBounds = self.bounds;     CGFloat dotsWidth = self.numberOfPages*kDotDiameter + MAX(0, self.numberOfPages-1)*kDotSpacer;     CGFloat x = CGRectGetMidX(currentBounds)-dotsWidth/2;     CGFloat y = CGRectGetMidY(currentBounds)-kDotDiameter/2;     for (int i=0; i<_numberOfPages; i++)     {         CGRect circleRect = CGRectMake(x, y, kDotDiameter, kDotDiameter);         if (i == _currentPage)         {             CGContextSetFillColorWithColor(context, self.dotColorCurrentPage.CGColor);         }         else         {             CGContextSetFillColorWithColor(context, self.dotColorOtherPage.CGColor);         }         CGContextFillEllipseInRect(context, circleRect);         x += kDotDiameter + kDotSpacer;     } }  - (void)dealloc  {     [dotColorCurrentPage release];     [dotColorOtherPage release];     [delegate release];     [super dealloc]; }  - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {     if (!self.delegate) return;      CGPoint touchPoint = [[[event touchesForView:self] anyObject] locationInView:self];      CGFloat dotSpanX = self.numberOfPages*(kDotDiameter + kDotSpacer);     CGFloat dotSpanY = kDotDiameter + kDotSpacer;      CGRect currentBounds = self.bounds;     CGFloat x = touchPoint.x + dotSpanX/2 - CGRectGetMidX(currentBounds);     CGFloat y = touchPoint.y + dotSpanY/2 - CGRectGetMidY(currentBounds);      if ((x<0) || (x>dotSpanX) || (y<0) || (y>dotSpanY)) return;      self.currentPage = floor(x/(kDotDiameter+kDotSpacer));     if ([self.delegate respondsToSelector:@selector(pageControlPageDidChange:)])     {         [self.delegate pageControlPageDidChange:self];     } }  @end 
vote vote

83

In iOS 6 you can set the tint color of UIPageControl:

There are 2 new properties:

  • pageIndicatorTintColor
  • currentPageIndicatorTintColor

You can also use the appearance API to change the tint color of all page indicators.

If you are targeting iOS 5 make sure it doesn't crash:

if ([pageControl respondsToSelector:@selector(setPageIndicatorTintColor:)]) {     pageControl.pageIndicatorTintColor = [UIColor whiteColor]; } 
vote vote

75

pageControl.pageIndicatorTintColor = [UIColor redColor]; pageControl.currentPageIndicatorTintColor = [UIColor redColor]; 

works for iOS6

vote vote

67

In case anyone wants an ARC / modern version of it (no need to redefine properties as ivar, no dealloc, and works with Interface Builder) :

#import <UIKit/UIKit.h>  @protocol PageControlDelegate;  @interface PageControl : UIView   // Set these to control the PageControl. @property (nonatomic) NSInteger currentPage; @property (nonatomic) NSInteger numberOfPages;  // Customize these as well as the backgroundColor property. @property (nonatomic, strong) UIColor *dotColorCurrentPage; @property (nonatomic, strong) UIColor *dotColorOtherPage;  // Optional delegate for callbacks when user taps a page dot. @property (nonatomic, weak) NSObject<PageControlDelegate> *delegate;  @end  @protocol PageControlDelegate<NSObject> @optional - (void)pageControlPageDidChange:(PageControl *)pageControl; @end 

PageControl.m :

#import "PageControl.h"   // Tweak these or make them dynamic. #define kDotDiameter 7.0 #define kDotSpacer 7.0  @implementation PageControl  @synthesize dotColorCurrentPage; @synthesize dotColorOtherPage; @synthesize currentPage; @synthesize numberOfPages; @synthesize delegate;  - (void)setCurrentPage:(NSInteger)page {     currentPage = MIN(MAX(0, page), self.numberOfPages-1);     [self setNeedsDisplay]; }  - (void)setNumberOfPages:(NSInteger)pages {     numberOfPages = MAX(0, pages);     currentPage = MIN(MAX(0, self.currentPage), numberOfPages-1);     [self setNeedsDisplay]; }  - (id)initWithFrame:(CGRect)frame  {     if (self = [super initWithFrame:frame])      {         // Default colors.         self.backgroundColor = [UIColor clearColor];         self.dotColorCurrentPage = [UIColor blackColor];         self.dotColorOtherPage = [UIColor lightGrayColor];     }     return self; }  -(id)initWithCoder:(NSCoder *)aDecoder {     if (self = [super initWithCoder:aDecoder])     {         self.dotColorCurrentPage = [UIColor blackColor];         self.dotColorOtherPage = [UIColor lightGrayColor];     }     return self; }  - (void)drawRect:(CGRect)rect  {     CGContextRef context = UIGraphicsGetCurrentContext();        CGContextSetAllowsAntialiasing(context, true);      CGRect currentBounds = self.bounds;     CGFloat dotsWidth = self.numberOfPages*kDotDiameter + MAX(0, self.numberOfPages-1)*kDotSpacer;     CGFloat x = CGRectGetMidX(currentBounds)-dotsWidth/2;     CGFloat y = CGRectGetMidY(currentBounds)-kDotDiameter/2;     for (int i=0; i<self.numberOfPages; i++)     {         CGRect circleRect = CGRectMake(x, y, kDotDiameter, kDotDiameter);         if (i == self.currentPage)         {             CGContextSetFillColorWithColor(context, self.dotColorCurrentPage.CGColor);         }         else         {             CGContextSetFillColorWithColor(context, self.dotColorOtherPage.CGColor);         }         CGContextFillEllipseInRect(context, circleRect);         x += kDotDiameter + kDotSpacer;     } }   - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {     if (!self.delegate) return;      CGPoint touchPoint = [[[event touchesForView:self] anyObject] locationInView:self];      CGFloat dotSpanX = self.numberOfPages*(kDotDiameter + kDotSpacer);     CGFloat dotSpanY = kDotDiameter + kDotSpacer;      CGRect currentBounds = self.bounds;     CGFloat x = touchPoint.x + dotSpanX/2 - CGRectGetMidX(currentBounds);     CGFloat y = touchPoint.y + dotSpanY/2 - CGRectGetMidY(currentBounds);      if ((x<0) || (x>dotSpanX) || (y<0) || (y>dotSpanY)) return;      self.currentPage = floor(x/(kDotDiameter+kDotSpacer));     if ([self.delegate respondsToSelector:@selector(pageControlPageDidChange:)])     {         [self.delegate pageControlPageDidChange:self];     } }  @end 
vote vote

51

The answer provided by Heiberg works really well, however the page control does not behave exactly like the one by apple.

If you want the page control to behave like the one from apple does (always increment the current page by one if you touch the second half, otherwise decrease by one), try this touchesBegan-method instead:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{      CGPoint touchPoint = [[[event touchesForView:self] anyObject] locationInView:self];      CGRect currentBounds = self.bounds;     CGFloat x = touchPoint.x - CGRectGetMidX(currentBounds);      if(x<0 && self.currentPage>=0){         self.currentPage--;         [self.delegate pageControlPageDidChange:self];      }     else if(x>0 && self.currentPage<self.numberOfPages-1){         self.currentPage++;         [self.delegate pageControlPageDidChange:self];      }    } 

Top 3 video Explaining iphone - How can I change the color of pagination dots of UIPageControl?

Related QUESTION?