自定义UIPageControl视图,用“Page X of Y”替换点

时间:2009-05-14 19:43:23

标签: iphone cocoa-touch uikit

我正试图找到一种方法来替换UIPageControl的点,其标题为“Y页面X”,因为我可能会有> 50项。我只是熟悉Cocoa,我想知道最好的方法是什么。我可以继承UIPageControl吗?我应该使用带标签的自定义视图吗?或其他什么?

修改

我最终使用Matt Gallagher的this代码来实现我的分页视图。它也更高效,因为它重新使用两个视图,而不是一次创建它们,就像在PageControl的Apple示例代码中所做的那样。

6 个答案:

答案 0 :(得分:27)

编辑:

这个答案已收到几个赞成票。谢谢你,但是对于所有来到这里的人,请注意UIPageControl 很容易实现!更重要的是,请查看我的回复和示例代码以获取一些想法,但您真的不应该在生产代码中使用它。如果你需要修改外观和版本,请滚动自己的UIControl子类。感觉UIPageControl。


原始回答:

UIPageControl没有做任何花哨的事情。对于大多数视图,视图本身要么在drawRect中绘制所有绘图,要么添加子视图并自己绘制。通过重写drawRect:而不是调用[super drawRect:],你确保如果实现是drawRect:-based你将拥有自己的绘图代码。对于UIPageControl,它依赖于已添加到UIPageControl的子视图。你真的不需要知道什么样的,你也不应该关心。这是Apple的实施,它可能会发生变化。

但是因为你知道它必须是drawRect:或基于子视图,你可以简单地删除UIPageControl的子视图,然后你的drawRect:override将按照你的期望工作(大多数情况下,你必须做一些额外的工作,以确保你在正确的时间重绘。)

这是一个示例,说明如何制作自己的自定义UIPageControl。精明的读者会注意到,一旦你遇到麻烦这样做,你可能只是创建了自己的页面控件作为UIControl的子类,并简单地实现了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

答案 1 :(得分:4)

我认为编写自定义页面控件不会违反人机界面指南。我想显示&gt;但是会有50个点;)

我认为双向进行是完全可以接受的。

您可以创建UIPageControl的自定义子类并覆盖默认的点绘制行为。您必须小心,不要覆盖您 需要的其他行为。

或者,由于UIPageControl类的重新实现并不是非常复杂,并且编写一个完整的新类将确保在覆盖点绘制逻辑时不会覆盖所需的行为,您可以重新实现它。如果这样做,请尝试使用Apple的变量命名。这样每个人都会立即知道如何使用你的课程。

答案 2 :(得分:3)

只需使用UILabel,并在滚动委托中设置带有“Page N of K”的格式字符串或其中的文本字符串。可以使用简单透明的UIButton添加不可见的左/右按钮。

如果您真的想自己编写UIControl子类,那么由您决定......

答案 3 :(得分:2)

另外,我应该添加任何考虑子类化UIPageControl的人(因为我来到这里(不幸的是)之后),因为某些骨干原因的类没有在drawRect:中绘制,或者任何其他公共方法。我怀疑在页面更新期间的某个时刻它会设置一个绘图上下文并用它的点填充它,但我在这里警告你:

  • 您无法在UIPageControl中覆盖drawRect:以便绘制自定义点而不是标准点。即使你得到你的绘图矩形来绘制你的点,UIPageControl将总是(耶!)绘制它的小白点。

这使得该类基本上不可子类化。当然,你可以,但为什么呢?

更重要的是,为什么苹果会让一个有着如此荒谬的异常行为的课程?! drawRect:是有原因的!这让我想起在早期图像浏览器时代与NSMatrix合作......

答案 4 :(得分:1)

虽然您可以继承UIPageControl,但我认为它不会添加任何东西。我建议您使用subClass UIControll并在UIPAgeControl的API上为您提供API。我认为用户界面是完全相同的。

您可以添加属性来控制文本,但可能不需要它。

答案 5 :(得分:0)

我找到了一个不错的自定义页面控件类:DDPageControl

它的行为与UIPageControl相同,你可以自定义它......