如何更改 UIPageControl 的分页点的颜色?

我正在开发一个应用程序,其中我要改变的颜色或图像的 UIPageControl分页点。我怎样才能改变它?是否有可能在上面的场景中定制 UIpageControl

112308 次浏览

从官方的角度来看,使用 iPhoneSDK 是不可能的。您可以使用私有方法来完成这项工作,但这将成为进入应用程序商店的一个障碍。

另一个安全的解决方案是创建您自己的页面控件,因为页面控件只显示当前在滚动视图中显示的页面,所以创建页面控件不会太困难。

更新:

这个答案已经有6年的历史了,而且非常过时,但它仍然吸引着投票和评论。自从 iOS 6.0以来,您应该在 UIPageControl上使用 pageIndicatorTintColorcurrentPageIndicatorTintColor属性。

原答案:

我今天碰到了这个问题,决定编写自己的简单替换类。

这是一个子级的 UIView,它使用核心图形来呈现您指定颜色的点。

您可以使用公开的属性来自定义和控制它。

如果需要,可以注册一个委托对象,以便在用户点击其中一个小点时获得通知。如果没有注册任何委托,则视图将不会对触摸输入做出反应。

刚从烤箱里拿出来的,不过看起来挺管用的。有什么问题就告诉我。

未来的改进:

  • 调整点的大小以适应电流 如果有太多的界限。
  • 不要重新绘制整个视图。正确:

示例使用:

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

头文件:

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

执行档案:

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

@ Jasarien 我认为你可以继承 UIPageControl 的子类,仅选自 apple doc 的一行“子类可以自定义页面控件的外观,当页面数量改变时,可以使用这个方法来调整页面控件的大小”,这是 sizeForNumberOfPages 方法:

Heiberg 提供的答案非常好用,但是页面控件的行为并不完全像 Apple 提供的那样。

如果希望页面控件的行为与苹果的页面控件类似(如果触摸后半部分,总是将当前页面增加一个,否则减少一个) ,可以尝试使用以下 touch esBegan-method:

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

您还可以使用 Three20 Library,它包含一个可设置样式的 PageControl 和几十个其他有用的 UI 控件和抽象。

如果有人想要一个 ARC/现代版本(不需要将属性重新定义为 ivar,不需要 dealloc,并使用 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

在 iOS6中,你可以设置 UIPageControl的色彩:

有两个新的属性:

  • pageIndicatorTintColor
  • currentPageIndicatorTintColor

您还可以使用外观 API 来更改所有页面指示器的色彩。

如果你的目标是 iOS5,确保它不会崩溃:

if ([pageControl respondsToSelector:@selector(setPageIndicatorTintColor:)]) {
pageControl.pageIndicatorTintColor = [UIColor whiteColor];
}
myView.superview.tintColor = [UIColor colorWithRed:1.0f
green:1.0f blue:1.0f alpha:1.0f];
pageControl.pageIndicatorTintColor = [UIColor redColor];
pageControl.currentPageIndicatorTintColor = [UIColor redColor];

适用于 iOS6

这在 iOS7中对我很有效。

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

将以下代码添加到 AppDelegate 中的 DidFinishLauch,

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

希望这个能帮上忙。

加上现有的答案,可以这样做,

enter image description here

您可以通过在 didFinishLaunchingWithOptions方法中向 应用程序代表文件添加以下代码轻松地修复它:

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

用这个来编程

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

或从故事板,你可以改变从当前的页面色彩

enter image description here

用 Swift 1.2很简单:

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

对于 Swift 2.0及以上的情况,下面的代码将起作用:

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

在 Swift 中,UIPageViewController 中的这段代码获取对页面指示器的引用并设置其属性

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()
}