Wie kann ich die Farbe der Paginierungspunkte von UIPageControl ändern?

178

Ich entwickle eine Anwendung, in der ich entweder die Farbe oder das Bild von UIPageControlPaginierungspunkten ändern möchte . Wie kann ich das ändern? Ist es möglich, das UIpageControlobige Szenario anzupassen ?

Tirth
quelle

Antworten:

266

AKTUALISIEREN:

Diese Antwort ist 6 Jahre alt und sehr veraltet, zieht aber immer noch Stimmen und Kommentare an. Seit iOS 6.0 sollten Sie die Eigenschaften pageIndicatorTintColorund currentPageIndicatorTintColorverwenden UIPageControl.

URSPRÜNGLICHE ANTWORT:

Ich bin heute auf dieses Problem gestoßen und habe beschlossen, meine eigene einfache Ersatzklasse zu schreiben.

Es ist eine untergeordnete UIView, die Core Graphics verwendet, um die Punkte in den von Ihnen angegebenen Farben zu rendern.

Sie verwenden die exponierten Eigenschaften, um sie anzupassen und zu steuern.

Wenn Sie möchten, können Sie ein Delegatenobjekt registrieren, um Benachrichtigungen zu erhalten, wenn der Benutzer auf einen der kleinen Seitenpunkte tippt. Wenn kein Delegat registriert ist, reagiert die Ansicht nicht auf Berührungseingaben.

Es ist völlig frisch aus dem Ofen, scheint aber zu funktionieren. Lassen Sie mich wissen, wenn Sie Probleme damit haben.

Zukünftige Verbesserungen:

  • Ändern Sie die Größe der Punkte, um sie an die aktuellen Grenzen anzupassen, wenn zu viele vorhanden sind.
  • Zeichnen Sie nicht die gesamte Ansicht in drawRect neu:

Anwendungsbeispiel:

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-Datei:

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

Implementierungsdatei:

//
//  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
Heiberg
quelle
Wie funktioniert das? Ich verwende die pagecontrolPageDidChange-Methode und erhalte nichts. Ich kann keine der Schaltflächen anklicken
Adam
Hallo Heiberg, ich habe dies verwendet, um meine Seite der Bildlaufansicht zu ändern. Wie machst du das mit deinem Code? [pageControl1 addTarget: self action: @selector (changePage :) forControlEvents: UIControlEventValueChanged];
Desmond
// Aktion zum Seitenwechsel in UIPageControl - (void) changePage: (UIPageControl *) control {// int page = pageControl.currentPage; int page = pageControl.currentPage; // aktualisiere die Bildlaufansicht auf die entsprechende Seite CGRect frame = scrollview.frame; frame.origin.x = frame.size.width * page; frame.origin.y = 0; [scrollview scrollRectToVisible: Rahmen animiert: JA]; pageControlUsed = YES; }
Desmond
Um diesen Code mit ARC auszuführen, müssen Sie lediglich die Dealloc-Methode entfernen, die Zuweisung in schwach ändern und vor der betreffenden Eigenschaftsdeklaration eine __schwache Methode hinzufügen. Sehr schön. Vielen Dank.
Cschuff
Ersetzen Sie NSObject <PageControlDelegate> * delegate durch __unsafe_unretained id delegate. im Header zur Lösung der ARC-Warnung
Mihir Mehta
150

In iOS 6 können Sie die Farbtonfarbe einstellen für UIPageControl:

Es gibt 2 neue Eigenschaften:

  • pageIndicatorTintColor
  • currentPageIndicatorTintColor

Sie können auch die Darstellungs-API verwenden, um die Farbtonfarbe aller Seitenindikatoren zu ändern.

Wenn Sie auf iOS 5 abzielen, stellen Sie sicher, dass es nicht abstürzt:

if ([pageControl respondsToSelector:@selector(setPageIndicatorTintColor:)]) {
    pageControl.pageIndicatorTintColor = [UIColor whiteColor];
}
Felix
quelle
Was ist mit iOS 5? Wie stellen Sie sicher, dass dies nicht abstürzt?
jjxtra
41
pageControl.pageIndicatorTintColor = [UIColor redColor];
pageControl.currentPageIndicatorTintColor = [UIColor redColor];

funktioniert für iOS6

Add080bbA
quelle
2
Ich war verblüfft, dass ich UIPageControl unterordnen musste. Das hat den Trick gemacht. Dies sollte sich auf Position 1 befinden.
Forrest
Warum ist eine so komplexe Antwort die am besten gewählte, wenn dies buchstäblich alles ist, was Sie brauchen?
TaylorAllred
23

Falls jemand eine ARC / moderne Version davon möchte (keine Notwendigkeit, Eigenschaften als ivar neu zu definieren, kein Dealloc und arbeitet mit 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
Ben G.
quelle
1
Eine kleine Ergänzung, um das Senden an den Delegierten zu stoppen, wenn sich die Seitenzahl nach einer Berührung nicht geändert hat. NSInteger newPage = floor (x / (kDotDiameter + kDotSpacer)); if (self.currentPage == newPage) return;
theLastNightTrain
15

Die Antwort von Heiberg funktioniert sehr gut, aber das Seitensteuerelement verhält sich nicht genau wie das von Apple.

Wenn Sie möchten, dass sich das Seitensteuerelement wie das von Apple verhält (erhöhen Sie die aktuelle Seite immer um eins, wenn Sie die zweite Hälfte berühren, andernfalls um eins verringern), versuchen Sie stattdessen diese touchBegan-Methode:

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

Fügen Sie DidFinishLauch in AppDelegate den folgenden Code hinzu:

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

Hoffe das wird helfen.

posha
quelle
6

Verwenden Sie dies zum Codieren

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

oder über das Storyboard können Sie die aktuelle Seitentönung ändern

Geben Sie hier die Bildbeschreibung ein

Pooja Patel
quelle
Danke ... weiter teilen :)
Tirth
6

In Swift erhält dieser Code im UIPageViewController einen Verweis auf die Seitenanzeige und legt deren Eigenschaften fest

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()
}
arbel03
quelle
UIPageControlist nicht dasselbe wieUIPageViewController
jungledev
5

Das Hinzufügen zu vorhandenen Antworten kann wie folgt erfolgen:

Geben Sie hier die Bildbeschreibung ein

A bis Z
quelle
4

Mit Swift 1.2 ist das ganz einfach:

UIPageControl.appearance().pageIndicatorTintColor           = UIColor.lightGrayColor()
UIPageControl.appearance().currentPageIndicatorTintColor    = UIColor.redColor()
Oleg Popov
quelle
3
Dies setzt es global. Wenn Ihre App mehrere UIPageControls enthält und Sie je nach Klasse unterschiedliche Farben benötigen, verwenden Sie UIPageControl.appearanceWhenContainedInInstancesOfClasses([MyClassName.self])stattdessen anstelle von UIPageControl.appearance(). Benötigt iOS 9.
Jon
4

Sie können das Problem problemlos beheben, indem Sie Ihrer appdelegate.m- Datei in Ihrer didFinishLaunchingWithOptionsMethode den folgenden Code hinzufügen :

UIPageControl *pageControl = [UIPageControl appearance];
pageControl.pageIndicatorTintColor = [UIColor darkGrayColor];
pageControl.currentPageIndicatorTintColor = [UIColor orangeColor];
pageControl.backgroundColor = [UIColor whiteColor]
Nabil El Atlas
quelle
3

Dies funktioniert für mich in iOS 7.

pageControl.pageIndicatorTintColor = [UIColor purpleColor];
pageControl.currentPageIndicatorTintColor = [UIColor magentaColor];
Sid
quelle
2

Es ist aus offizieller Sicht nicht möglich, das iPhone SDK zu verwenden. Möglicherweise können Sie dies mit privaten Methoden tun, dies ist jedoch ein Hindernis für den Zugriff auf den App Store.

Die einzige andere sichere Lösung besteht darin, ein eigenes Seitensteuerelement zu erstellen, das nicht allzu schwierig sein sollte, da das Seitensteuerelement einfach anzeigt, welche Seite derzeit in einer Bildlaufansicht angezeigt wird.

Jasarien
quelle
Theere ist kein Link zu meiner Lösung. Meine Lösung befindet sich im Text direkt über Ihrem Kommentar. Suchen Sie entweder nach den privaten Methoden (ich weiß nicht, was diese sind) oder schreiben Sie Ihre eigenen (ich werde das nicht für Sie tun).
Jasarien
2

@Jasarien Ich denke, Sie können UIPageControll unterordnen, Zeile nur aus Apple Doc ausgewählt. "Unterklassen, die das Erscheinungsbild des Seitensteuerelements anpassen, können diese Methode verwenden, um die Größe des Seitensteuerelements zu ändern, wenn sich die Seitenzahl ändert" für die Methode sizeForNumberOfPages:

dsaw
quelle
2

Sie können auch die Three20-Bibliothek verwenden, die ein stilisierbares PageControl und Dutzende anderer hilfreicher Steuerelemente und Abstraktionen für die Benutzeroberfläche enthält.

cschuff
quelle
2

Ab Swift 2.0und zu funktioniert der folgende Code:

pageControl.pageIndicatorTintColor = UIColor.whiteColor()
pageControl.currentPageIndicatorTintColor = UIColor.redColor()
Sohil R. Memon
quelle
-1
myView.superview.tintColor = [UIColor colorWithRed:1.0f  
                                      green:1.0f blue:1.0f alpha:1.0f];
Michael Belanger
quelle