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

IphoneIosUipagecontrol

Iphone Problem Overview


I am developing an application in which I want to change either color or image of UIPageControl pagination dots. How can I change it? Is it possible to customize UIpageControl on above scenario?

Iphone Solutions


Solution 1 - Iphone

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 <[email protected]> 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 <[email protected]> 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

Solution 2 - Iphone

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];
}

Solution 3 - Iphone

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

works for iOS6

Solution 4 - Iphone

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

Solution 5 - Iphone

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]; 
    }   
}

Solution 6 - Iphone

Add the following code to DidFinishLauch in AppDelegate,

UIPageControl *pageControl = [UIPageControl appearance];
pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
pageControl.currentPageIndicatorTintColor = [UIColor blackColor];
pageControl.backgroundColor = [UIColor whiteColor];

Hope this will help.

Solution 7 - Iphone

In Swift, this code inside the UIPageViewController is getting a reference to the page indicator and setting its properties

override func viewDidLoad() {
    super.viewDidLoad()
    
    //Creating the proxy
    let pageControl = UIPageControl.appearance()
    //Customizing
    pageControl.pageIndicatorTintColor = UIColor.lightGrayColor()
    pageControl.currentPageIndicatorTintColor = UIColor.darkGrayColor()
    //Setting the background of the view controller so the dots wont be on a black background   
    self.view.backgroundColor = UIColor.whiteColor()
}

Solution 8 - Iphone

use this for coding

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

or from storyboard you can change from current page tint

enter image description here

Solution 9 - Iphone

Adding to existing answers, it can be done like,

enter image description here

Solution 10 - Iphone

You can fix it with ease by adding the following code to your appdelegate.m file in your didFinishLaunchingWithOptions method:

UIPageControl *pageControl = [UIPageControl appearance];
pageControl.pageIndicatorTintColor = [UIColor darkGrayColor];
pageControl.currentPageIndicatorTintColor = [UIColor orangeColor];
pageControl.backgroundColor = [UIColor whiteColor]

Solution 11 - Iphone

This is worked for me in iOS 7.

pageControl.pageIndicatorTintColor = [UIColor purpleColor];
pageControl.currentPageIndicatorTintColor = [UIColor magentaColor];

Solution 12 - Iphone

It's easy with Swift 1.2:

UIPageControl.appearance().pageIndicatorTintColor           = UIColor.lightGrayColor()
UIPageControl.appearance().currentPageIndicatorTintColor    = UIColor.redColor()

Solution 13 - Iphone

In cased of Swift 2.0 and up, the below code will work:

pageControl.pageIndicatorTintColor = UIColor.whiteColor()
pageControl.currentPageIndicatorTintColor = UIColor.redColor()

Solution 14 - Iphone

@Jasarien I think you can subclass UIPageControll, line picked from apple doc only "Subclasses that customize the appearance of the page control can use this method to resize the page control when the page count changes" for the method sizeForNumberOfPages:

Solution 15 - Iphone

You could also use Three20 Library that contains a styleable PageControl and dozens of other helpful UI Controls and Abstractions.

Solution 16 - Iphone

It's not possible using the iPhone SDK from an official standpoint. You might be able to do it using private methods, but that will be a barrier to getting onto the app store.

The only other safe solution is to create yout own page control which shpuldnt be too difficult given that the page control simply displays what page is currently shown in a scroll view.

Solution 17 - Iphone

myView.superview.tintColor = [UIColor colorWithRed:1.0f  
                                      green:1.0f blue:1.0f alpha:1.0f];

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
QuestionTirthView Question on Stackoverflow
Solution 1 - IphoneHeibergView Answer on Stackoverflow
Solution 2 - IphoneFelixView Answer on Stackoverflow
Solution 3 - IphoneAdd080bbAView Answer on Stackoverflow
Solution 4 - IphoneBen GView Answer on Stackoverflow
Solution 5 - IphoneChristophKView Answer on Stackoverflow
Solution 6 - IphoneposhaView Answer on Stackoverflow
Solution 7 - Iphonearbel03View Answer on Stackoverflow
Solution 8 - IphonePooja PatelView Answer on Stackoverflow
Solution 9 - IphoneaTozView Answer on Stackoverflow
Solution 10 - IphoneNabil El AtlasView Answer on Stackoverflow
Solution 11 - IphoneSidView Answer on Stackoverflow
Solution 12 - IphoneOleg PopovView Answer on Stackoverflow
Solution 13 - IphoneSohil R. MemonView Answer on Stackoverflow
Solution 14 - IphonedsawView Answer on Stackoverflow
Solution 15 - IphonecschuffView Answer on Stackoverflow
Solution 16 - IphoneJasarienView Answer on Stackoverflow
Solution 17 - IphoneMichael BelangerView Answer on Stackoverflow