Как я могу изменить цвет точек разбиения на страницы UIPageControl?
Я разрабатываю приложение, в котором я хочу, чтобы изменить цвет или изображение UIPageControl
точки разбиения на страницы. Как я могу это изменить? Можно ли настроить UIpageControl
по вышеуказанному сценарию?
18 ответов:
обновление:
этот ответ 6 лет и очень устарел, но он все еще привлекает голоса и комментарии. Начиная с iOS 6.0 вы должны использовать
pageIndicatorTintColor
иcurrentPageIndicatorTintColor
свойстваUIPageControl
.ОРИГИНАЛЬНЫЙ ОТВЕТ:
я столкнулся с этой проблемой сегодня и решил написать свой собственный простой класс замены.
это подзаголовок UIView, который использует основную графику для визуализации точек в цветах, которые вы указывать.
вы используете открытые свойства для настройки и управления им.
если вы хотите вы можете зарегистрировать объект делегата, чтобы получать уведомления, когда пользователь нажимает на одну из маленьких точек страницу. Если делегат не зарегистрирован, то представление не будет реагировать на сенсорный ввод.
он полностью свежий из духовки, но, кажется, работает. Дайте мне знать, если у вас возникнут какие-либо проблемы с ним.
будущие усовершенствования:
- изменить размер точки, чтобы соответствовать текущему границы, если их слишком много.
- не перерисовывайте весь вид в 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
в iOS 6 Вы можете установить оттенок цвета
UIPageControl
:есть 2 новых свойства:
pageIndicatorTintColor
currentPageIndicatorTintColor
вы также можете использовать внешний вид API, чтобы изменить оттенок цвета всех индикаторов страницы.
если вы нацелены на iOS 5, убедитесь, что он не падает:
if ([pageControl respondsToSelector:@selector(setPageIndicatorTintColor:)]) { pageControl.pageIndicatorTintColor = [UIColor whiteColor]; }
pageControl.pageIndicatorTintColor = [UIColor redColor]; pageControl.currentPageIndicatorTintColor = [UIColor redColor];
работает для iOS6
в случае, если кто-то хочет дугу / современную версию (нет необходимости переопределять свойства как 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.м :
#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
ответ, предоставленный Heiberg, работает очень хорошо, однако элемент управления страницей ведет себя не совсем так, как apple.
Если вы хотите, чтобы элемент управления страницей вел себя так, как это делает apple (всегда увеличивайте текущую страницу на одну, если вы касаетесь второй половины, иначе уменьшите на одну), попробуйте этот touchesBegan-метод вместо этого:
- (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]; } }
добавьте следующий код в DidFinishLauch в AppDelegate,
UIPageControl *pageControl = [UIPageControl appearance]; pageControl.pageIndicatorTintColor = [UIColor lightGrayColor]; pageControl.currentPageIndicatorTintColor = [UIColor blackColor]; pageControl.backgroundColor = [UIColor whiteColor];
надеюсь, что это поможет.
в 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() }
Это легко с Swift 1.2:
UIPageControl.appearance().pageIndicatorTintColor = UIColor.lightGrayColor() UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.redColor()
это работает для меня в iOS 7.
pageControl.pageIndicatorTintColor = [UIColor purpleColor]; pageControl.currentPageIndicatorTintColor = [UIColor magentaColor];
Вы можете исправить это с легкостью, добавив следующий код appdelegate.м в своем
didFinishLaunchingWithOptions
способ:UIPageControl *pageControl = [UIPageControl appearance]; pageControl.pageIndicatorTintColor = [UIColor darkGrayColor]; pageControl.currentPageIndicatorTintColor = [UIColor orangeColor]; pageControl.backgroundColor = [UIColor whiteColor]
невозможно использовать iPhone SDK с официальной точки зрения. Возможно, вы сможете сделать это с помощью частных методов, но это будет препятствием для входа в магазин приложений.
единственное безопасное решение-создать собственный элемент управления страницей, который не будет слишком сложным, учитывая, что элемент управления страницей просто отображает, какая страница в настоящее время отображается в виде прокрутки.
@Jasarien я думаю, что вы можете подкласс UIPageControll, строка, выбранная из apple doc только "подклассы, которые настраивают внешний вид элемента управления страницей, могут использовать этот метод для изменения размера элемента управления страницей при изменении количества страниц" для метода sizeForNumberOfPages:
вы также можете использовать библиотеку Three20, которая содержит styleable PageControl и десятки других полезных элементов управления и абстракций пользовательского интерфейса.
в случае
Swift 2.0
и выше, ниже код будет работать:pageControl.pageIndicatorTintColor = UIColor.whiteColor() pageControl.currentPageIndicatorTintColor = UIColor.redColor()
вот решение Swift 3.0 ... вы знаете, если вы в порядке с принятием заявленного риска:"изменение подвидов существующего элемента управления является хрупким".
вам нужно будет вызвать updateDots() в вашем viewDidAppear () и ваш обработчик valueChanged для элемента управления page.
import UIKit class CustomImagePageControl: UIPageControl { let activeImage:UIImage = UIImage(named: "SelectedPage")! let inactiveImage:UIImage = UIImage(named: "UnselectedPage")! override func awakeFromNib() { super.awakeFromNib() self.pageIndicatorTintColor = UIColor.clear self.currentPageIndicatorTintColor = UIColor.clear self.clipsToBounds = false } func updateDots() { var i = 0 for view in self.subviews { if let imageView = self.imageForSubview(view) { if i == self.currentPage { imageView.image = self.activeImage } else { imageView.image = self.inactiveImage } i = i + 1 } else { var dotImage = self.inactiveImage if i == self.currentPage { dotImage = self.activeImage } view.clipsToBounds = false view.addSubview(UIImageView(image:dotImage)) i = i + 1 } } } fileprivate func imageForSubview(_ view:UIView) -> UIImageView? { var dot:UIImageView? if let dotImageView = view as? UIImageView { dot = dotImageView } else { for foundView in view.subviews { if let imageView = foundView as? UIImageView { dot = imageView break } } } return dot } }