I\'m trying to find a way to replace the dots of a UIPageControl with a caption that reads \"Page X of Y\" since I\'ll likely have >50 items. I\'m just becoming familiar with Co
I found a nice custom page control class: DDPageControl
The behavior it's the same as the UIPageControl and you can customize it...
Although you can subclass UIPageControl, I don't think it will add anything. I suggest you subClass UIControll and base you API on UIPAgeControl's API. I think the UIs would be identical.
You could add properties to control the text but it's probably not needed.
I don't think writing a custom page control will violate the the Human Interface Guidelines. I think showing > 50 dots would though ;)
I think it's perfectly acceptable to go both ways.
You could create a custom subclass of UIPageControl and override the default dot drawing behavior. You'd have to be careful not to override other behavior you do need.
Or, since the UIPageControl class isn't horribly complex to re-implement and writing a entire new class will make sure you don't override behavior you need when you override the dot drawing logic, you could just re-implement it. If you do, try to use Apple's naming of variables. This way everybody will immediately know how to use your class.
Also, I should add for anyone considering subclassing UIPageControl (as I came here (unfortunately) after doing), the class for some boneheaded reason doesn't do its drawing in drawRect:, or any other public method for that matter. I suspect that at some point during page updates it sets up a drawing context and fills it with its dots, but I am here to warn you:
This makes the class essentially un-subclassable. Sure, you could, but why?
And more importantly, why would apple make a class with such ridiculously abnormal behavior?! drawRect: is there for a reason! This reminds me of working with NSMatrix back in the pre- imagebrowser days...
EDIT:
This answer has received several upvotes. Thank you but for all who come here please realize that the UIPageControl is very easy to implement yourself! More to the point, take a look at my response and sample code below for some ideas but you really shouldn't use it in production code. Roll your own subclass of UIControl if you need to modify the look & feel of a UIPageControl.
ORIGINAL ANSWER:
The UIPageControl isn't doing anything fancy. For most views the view itself either does all its drawing in drawRect: or it adds subviews and those draw themselves. By overriding drawRect: and not calling [super drawRect:] you ensure that if the implementation is drawRect:-based you'll have your own drawing code called. In the case of UIPageControl, it relies on subviews that have been added to UIPageControl. You don't really need to know what kind though nor should you care. It's Apple's implementation and it's subject to change.
But because you know it has to be either drawRect: or subview-based, you can get away with simply removing the subviews of the UIPageControl and then your drawRect: override will work as you'd expect (mostly, you have to do a little bit of extra work to make sure you redraw at the right times).
Here's an example that shows how to make your own custom UIPageControl. The astute reader will notice that once you've gone to the trouble to do it this way you might as well have just created your own page control as a subclass of UIControl and simply implemented the UIPageControl API.
//
// RedGreyPageControl.m
//
@interface RedGreyPageControl : UIPageControl {
NSArray *originalSubviews;
}
@end
@implementation RedGreyPageControl
// This assumes you're creating the control from a nib. Depending on your
// usage you might do this step in initWithFrame:
- (void) awakeFromNib {
// retain original subviews in case apple's implementation
// relies on the retain count being maintained by the view's
// presence in its superview.
originalSubviews = [[NSArray alloc] initWithArray: self.subviews];
for ( UIView *view in self.subviews ) [view removeFromSuperview];
// make sure the view is redrawn not scaled when the device is rotated
self.contentMode = UIViewContentModeRedraw;
}
- (void) dealloc {
[originalSubviews release];
[super dealloc];
}
- (void) drawRect:(CGRect) iRect {
UIImage *grey, *image, *red;
int i;
CGRect rect;
const CGFloat kSpacing = 10.0;
iRect = self.bounds;
if ( self.opaque ) {
[self.backgroundColor set];
UIRectFill( iRect );
}
if ( self.hidesForSinglePage && self.numberOfPages == 1 ) return;
red = [UIImage imageNamed: @"circle_graphic_red.png"];
grey = [UIImage imageNamed: @"circle_graphic_grey.png"];
rect.size.height = red.size.height;
rect.size.width = self.numberOfPages * red.size.width + ( self.numberOfPages - 1 ) * kSpacing;
rect.origin.x = floorf( ( iRect.size.width - rect.size.width ) / 2.0 );
rect.origin.y = floorf( ( iRect.size.height - rect.size.height ) / 2.0 );
rect.size.width = red.size.width;
for ( i = 0; i < self.numberOfPages; ++i ) {
image = i == self.currentPage ? red : grey;
[image drawInRect: rect];
rect.origin.x += red.size.width + kSpacing;
}
}
// you must override the setCurrentPage: and setNumberOfPages:
// methods to ensure that your control is redrawn when its values change
- (void) setCurrentPage:(NSInteger) iPage {
[super setCurrentPage: iPage];
[self setNeedsDisplay];
}
- (void) setNumberOfPages:(NSInteger) iPages {
[super setNumberOfPages: iPages];
[self setNeedsDisplay];
}
@end
Just use a UILabel and set its text w/ a format string in your scroll delegate that says "Page N of K" or somesuch. Invisible left/right buttons can be added with simple transparent UIButton
s.
Up to you if you really want to write the UIControl subclass yourself....