ฉันจะเปลี่ยนสีของจุดแบ่งหน้าของ UIPageControl ได้อย่างไร


178

ฉันกำลังพัฒนาแอปพลิเคชันที่ฉันต้องการเปลี่ยนสีหรือรูปภาพของUIPageControlจุดแบ่งเลข ฉันจะเปลี่ยนได้อย่างไร มันเป็นไปได้ที่จะปรับแต่งUIpageControlในสถานการณ์ข้างต้น?

คำตอบ:


266

UPDATE:

คำตอบนี้มีอายุ 6 ปีและล้าสมัยมาก แต่ก็ยังคงดึงดูดการลงคะแนนและความคิดเห็น นับตั้งแต่ iOS 6.0 ที่คุณควรจะใช้pageIndicatorTintColorและคุณสมบัติในการcurrentPageIndicatorTintColorUIPageControl

คำตอบเดิม:

ฉันพบปัญหานี้ในวันนี้และตัดสินใจที่จะเขียนคลาสการทดแทนอย่างง่ายของฉันเอง

เป็น UIView แบบ sublass ที่ใช้ Core Graphics เพื่อแสดงจุดในสีที่คุณระบุ

คุณใช้คุณสมบัติที่เปิดเผยเพื่อกำหนดเองและควบคุม

หากคุณต้องการคุณสามารถลงทะเบียนวัตถุผู้รับมอบสิทธิ์เพื่อรับการแจ้งเตือนเมื่อผู้ใช้แตะที่หนึ่งในจุดเล็ก ๆ ของหน้า หากไม่ได้ลงทะเบียนผู้ร่วมประชุมมุมมองจะไม่ตอบสนองต่อการป้อนข้อมูลแบบสัมผัส

มันสดใหม่จากเตาอบ แต่ดูเหมือนว่าจะทำงาน แจ้งให้เราทราบหากคุณพบปัญหาใด ๆ กับมัน

การปรับปรุงในอนาคต:

  • ปรับขนาดของจุดให้พอดีกับขอบเขตปัจจุบันหากมีจำนวนมากเกินไป
  • อย่าวาดมุมมองทั้งหมดอีกครั้งใน drawRect:

ตัวอย่างการใช้:

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

แล้วมันทำงานอย่างไร ฉันใช้ pagecontrolPageDidChange และฉันไม่ได้อะไรเลย ฉันไม่สามารถคลิกปุ่มใด ๆ ได้เลย
อดัม

สวัสดี, ฉันใช้สิ่งนี้เพื่อเปลี่ยนหน้าของ scrollview ของคุณ, คุณจะทำอย่างไรจากโค้ดของคุณ? [pageControl1 addTarget: self action: @selector (changePage :) forControlEvents: UIControlEventValueChanged];
Desmond

// การกระทำสำหรับการเปลี่ยนหน้าใน UIPageControl - (void) changePage: (UIPageControl *) ควบคุม {// int หน้า = pageControl.currentPage; int หน้า = pageControl.currentPage; // อัปเดตมุมมองเลื่อนไปยังหน้าที่เหมาะสม CGRect frame = scrollview.frame; frame.origin.x = frame.size.width * หน้า; frame.origin.y = 0; [scrollview scrollRectToVisible: เฟรมเคลื่อนไหว: ใช่]; pageControlUsed = YES; }
Desmond

สำหรับการเรียกใช้รหัสนี้ด้วย ARC คุณเพียงแค่ต้องลบเมธอด dealloc เปลี่ยนการกำหนดเป็นอ่อนและเพิ่ม __ อ่อนแอก่อนที่จะประกาศคุณสมบัติที่เกี่ยวข้อง ดีมาก. ขอบคุณมาก.
cschuff

แทนที่ NSObject <PageControlDelegate> * มอบหมายด้วย __unsafe_unretained id delegate; ในส่วนหัวเพื่อแก้ไขคำเตือน ARC
Mihir Mehta

150

ใน iOS 6 คุณสามารถตั้งค่าสีอ่อนของUIPageControl:

มี 2 ​​คุณสมบัติใหม่:

  • pageIndicatorTintColor
  • currentPageIndicatorTintColor

คุณยังสามารถใช้ API ลักษณะที่ปรากฏเพื่อเปลี่ยนสีอ่อนของตัวบ่งชี้หน้าทั้งหมด

หากคุณกำหนดเป้าหมายไปที่ iOS 5 ตรวจสอบให้แน่ใจว่าไม่มีข้อผิดพลาด:

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

แล้ว iOS 5 ล่ะ? คุณแน่ใจได้อย่างไรว่าสิ่งนี้จะไม่พัง
jjxtra

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

ใช้งานได้กับ iOS6


2
ฉันรู้สึกว่าฉันต้อง subclass UIPageControl นี่เป็นการหลอกลวง นี่ควรจะอยู่ที่ตำแหน่งที่ 1
ฟอเรสต์

ทำไมคำตอบที่ซับซ้อนเช่นนี้จึงเป็นคำตอบที่ได้รับการโหวตสูงสุดเมื่อคุณต้องการสิ่งนี้อย่างแท้จริง
TaylorAllred

23

ในกรณีที่ทุกคนต้องการ ARC / เวอร์ชันทันสมัยของมัน (ไม่จำเป็นต้องกำหนดคุณสมบัติใหม่เป็น ivar, no 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

1
นอกจากนี้เล็กน้อยเพื่อหยุดการส่งไปยังผู้รับมอบสิทธิ์หากหมายเลขหน้าไม่เปลี่ยนแปลงหลังจากการสัมผัส NSInteger newPage = floor (x / (kDotDiameter + kDotSpacer)); ถ้า (self.currentPage == newPage) ส่งคืน;
theLastNightTrain

15

คำตอบที่ได้รับจาก Heiberg ทำงานได้ดีจริงๆ แต่การควบคุมหน้ากระดาษไม่ได้ทำงานเหมือนกับแอปเปิ้ล

หากคุณต้องการให้ตัวควบคุมหน้าทำงานเหมือนที่แอปเปิลทำ (ให้เพิ่มหน้าปัจจุบันทีละหน้าถ้าคุณแตะครึ่งหลังหรือลดลงทีละหนึ่ง) ให้ลองใช้วิธีการสัมผัสขั้นต้นแทน:

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

8

เพิ่มรหัสต่อไปนี้เพื่อ DidFinishLauch ใน AppDelegate

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

หวังว่าจะช่วยได้


6

ใช้สำหรับการเข้ารหัส

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

หรือจากกระดานเรื่องราวคุณสามารถเปลี่ยนจากโทนสีของหน้าปัจจุบัน

ป้อนคำอธิบายรูปภาพที่นี่


ขอบคุณ ... แบ่งปันต่อไป :)
Tirth

6

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

UIPageControlไม่เหมือนกับUIPageViewController
jungledev


4

ง่ายด้วย Swift 1.2:

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

3
ชุดนี้มันทั่วโลก ถ้าคุณมีหลาย UIPageControls ใน app ของคุณและคุณจำเป็นต้องสีที่แตกต่างกันขึ้นอยู่กับชั้นแล้วใช้แทนUIPageControl.appearanceWhenContainedInInstancesOfClasses([MyClassName.self]) UIPageControl.appearance()ต้องใช้ iOS 9.
Jon

4

คุณสามารถแก้ไขได้อย่างง่ายดายโดยเพิ่มรหัสต่อไปนี้ไปยังไฟล์appdelegate.mในdidFinishLaunchingWithOptionsวิธีการของคุณ:

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

3

สิ่งนี้ใช้ได้กับฉันใน iOS 7

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

2

ไม่สามารถใช้ iPhone SDK จากมุมมองอย่างเป็นทางการ คุณอาจสามารถทำได้โดยใช้วิธีการส่วนตัว แต่นั่นจะเป็นอุปสรรคในการเข้าถึงแอพสโตร์

โซลูชันที่ปลอดภัยอื่น ๆ เพียงอย่างเดียวคือการสร้างการควบคุมหน้าของคุณเองซึ่ง shpuldnt นั้นยากเกินไปเนื่องจากการควบคุมหน้าจะแสดงเพียงแค่หน้าใดที่แสดงอยู่ในมุมมองแบบเลื่อน


นี่ไม่ใช่ลิงก์ไปยังโซลูชันของฉัน ทางออกของฉันมีอยู่ในข้อความเหนือความคิดเห็นของคุณ มองหาวิธีการส่วนตัว (ฉันจะไม่รู้ว่ามันคืออะไร) หรือเขียนของคุณเอง (ฉันจะไม่ทำเพื่อคุณ)
Jasarien

2

@Jasarien ฉันคิดว่าคุณสามารถ subclass UIPageControll, บรรทัดที่เลือกจาก apple doc เท่านั้น "Subclasses ที่กำหนดลักษณะที่ปรากฏของการควบคุมหน้าสามารถใช้วิธีนี้เพื่อปรับขนาดการควบคุมหน้าเมื่อเปลี่ยนจำนวนหน้า" สำหรับวิธี sizeForNumberOfPages:


2

คุณสามารถใช้ไลบรารี Three20 ที่มี PageControl ที่มีสไตล์และอีกหลายสิบตัวควบคุม UI ที่เป็นประโยชน์และ Abstractions


2

ในกรณีที่มีSwift 2.0และน้อยกว่ารหัสด้านล่างจะทำงาน:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.