UIPageControl本身没用吗?

时间:2009-07-09 13:31:08

标签: iphone objective-c uikit scroll paging

我一直在研究如何使用UIPageControl作为应用程序的滚动部分,我想知道它是如何工作的。文档显示了更改页面,设置页面数等的方法,但页面控件本身并不包含任何类型的滚动视图。

当想要显示页面指示符时,UIPageControl和UIScrollView类是否应该结合使用(就像iPhone的主屏幕上有app页面一样)?

5 个答案:

答案 0 :(得分:20)

我编写了一个类(PagedView),它的工作方式与UITableView类似,并以iPhone主屏幕上的方式合​​并UIPageControl和UIScrollView的概念。

概念基本如下:您需要实现PagedViewDelegate以返回PagedView的每个页面的页数和视图。重用视图与UITableView中的相同。使用界面构建器连接scrollview和pageControl出口。

如果您觉得这门课有用,请告诉我。

.H-文件:

//
//  PagedView.h
//
//  Created by Werner Altewischer on 22/10/10.
//  Copyright 2010 werner-it.com. All rights reserved.
//

@protocol ReusableObject

- (NSString *)reuseIdentifier;
- (void)prepareForReuse;

@end

@class PagedView;

@protocol PagedViewDelegate

- (NSUInteger)numberOfPagesInPagedView:(PagedView *)view;
- (UIView *)pagedView:(PagedView *)view viewForPageAtIndex:(NSUInteger)page;

@end

@interface PagedView : UIView<UIScrollViewDelegate> {
    IBOutlet UIScrollView *scrollView;
    IBOutlet UIPageControl *pageControl;
    NSMutableDictionary *pageViewDictionary;
    NSMutableDictionary *reuseViewDictionary;

    IBOutlet id <PagedViewDelegate> delegate;
}

@property (nonatomic, assign) IBOutlet id <PagedViewDelegate> delegate;

- (UIView<ReusableObject> *)dequeueReusableViewWithIdentifier:(NSString *)identifier;

- (void)scrollToPageAtIndex:(NSUInteger)pageIndex animated:(BOOL)animated;
- (NSInteger)indexForSelectedPage;

- (CGSize)pageSize;
- (void)reloadData;

@end

的.m-文件:

//
//  PagedView.m
//
//  Created by Werner Altewischer on 22/10/10.
//  Copyright 2010 werner-it.com. All rights reserved.
//



#define TT_RELEASE_SAFELY(__POINTER) { [__POINTER release]; __POINTER = nil; }

    @interface PagedView (Private)

    - (NSUInteger)pageCount;

    - (UIView *)loadViewForIndex:(NSUInteger)pageIndex;
    - (void)unloadViewForIndex:(NSUInteger)pageIndex;
    - (void)loadViewsForVisiblePages:(BOOL)reloadData;  
    - (UIView *)viewForIndex:(NSUInteger)pageIndex;

    @end

    @implementation PagedView

    @synthesize delegate;

    - (void)dealloc {
        TT_RELEASE_SAFELY(pageViewDictionary);
        TT_RELEASE_SAFELY(reuseViewDictionary);
        TT_RELEASE_SAFELY(scrollView);
        TT_RELEASE_SAFELY(pageControl);
        [super dealloc];
    }

    - (CGSize)pageSize {
        return scrollView.frame.size;
    }

    - (void)reloadData {
        if (!pageViewDictionary) {
            //First time initialization 
            pageViewDictionary = [NSMutableDictionary new];
            reuseViewDictionary = [NSMutableDictionary new];
            [pageControl addTarget:self action:@selector(pageChanged:) forControlEvents:UIControlEventValueChanged];
            scrollView.delegate = self;
            scrollView.pagingEnabled = YES;
        }

        CGSize size = self.pageSize;

        NSUInteger numberOfPages = self.pageCount;  
        pageControl.numberOfPages = MAX(1, numberOfPages);
        [scrollView setContentSize:CGSizeMake(size.width * numberOfPages, size.height)];
        pageControl.currentPage = self.indexForSelectedPage;

        pageControl.hidden = (numberOfPages == 0);

        [self loadViewsForVisiblePages:YES];
    }

    - (void)layoutSubviews {
        if (!pageViewDictionary) {
            [self reloadData];
        }
    }

    - (void)scrollToPageAtIndex:(NSUInteger)pageIndex animated:(BOOL)animated {
        if (pageIndex < self.pageCount) {
            CGSize size = scrollView.frame.size;
            CGRect rect = CGRectMake(size.width * pageIndex, 0, size.width, size.height);
            [scrollView scrollRectToVisible:rect animated:animated];
        }
    }

    - (NSInteger)indexForSelectedPage {
        CGFloat cx = scrollView.contentOffset.x;
        NSUInteger index = (NSUInteger)(cx / scrollView.frame.size.width);
        if (index >= self.pageCount) {
            index = NSNotFound;
        }
        return index;
    }

    #pragma mark -
    #pragma mark UIScrollViewDelegate implementation

    - (void)scrollViewWillBeginDragging:(UIScrollView *)theScrollView {
        theScrollView.userInteractionEnabled = NO; 
    }

    - (void)scrollViewDidEndDecelerating:(UIScrollView *)theScrollView {
        if (theScrollView == scrollView) {
            pageControl.currentPage = self.indexForSelectedPage;
            [self loadViewsForVisiblePages:NO];
            theScrollView.userInteractionEnabled = YES; 
        }
    }

    - (void)pageChanged:(UIPageControl *)thePageControl {
        if (pageControl == thePageControl) {
            [self scrollToPageAtIndex:pageControl.currentPage animated:YES];
            [self loadViewsForVisiblePages:NO];
        }
    }

    - (UIView<ReusableObject> *)dequeueReusableViewWithIdentifier:(NSString *)identifier {
        UIView<ReusableObject> *v = [[[reuseViewDictionary objectForKey:identifier] retain] autorelease];
        if (v) {
            [v prepareForReuse];
            [reuseViewDictionary removeObjectForKey:identifier];
        }
        return v;
    }

    @end


    @implementation PagedView (Private)

    - (NSUInteger)pageCount {
        return [self.delegate numberOfPagesInPagedView:self];
    }

    - (UIView *)viewForIndex:(NSUInteger)pageIndex {
        id key = [NSNumber numberWithUnsignedInteger:pageIndex];
        return [pageViewDictionary objectForKey:key];
    }

    - (UIView *)loadViewForIndex:(NSUInteger)pageIndex {
        id key = [NSNumber numberWithUnsignedInteger:pageIndex];
        UIView *v = [pageViewDictionary objectForKey:key];
        if (!v) {
            CGSize size = self.pageSize;
            UIView *v = [self.delegate pagedView:self viewForPageAtIndex:pageIndex];
            if (v) {
                v.frame = CGRectMake(pageIndex * size.width, 0, size.width, size.height);
                [scrollView addSubview:v];      
                [pageViewDictionary setObject:v forKey:key];
            }
        } 
        return v;
    }

    - (void)unloadViewForIndex:(NSUInteger)pageIndex {
        id key = [NSNumber numberWithUnsignedInteger:pageIndex];
        UIView *v = [pageViewDictionary objectForKey:key];
        if (v) {
            if ([v conformsToProtocol:@protocol(ReusableObject)]) {
                NSString *reuseIdentifier = [(id <ReusableObject>)v reuseIdentifier];
                [reuseViewDictionary setObject:v forKey:reuseIdentifier];
            }
            [v removeFromSuperview];
            [pageViewDictionary removeObjectForKey:key];
        }

    }

    - (void)loadViewsForVisiblePages:(BOOL)reloadData {

        //load the selected view and the one in front and behind

        NSUInteger selectedPage = self.indexForSelectedPage;
        NSUInteger numberOfPages = self.pageCount;

        int intSelectedPage = (selectedPage == NSNotFound) ? -2 : (int)selectedPage;

        //Find the max number present in the pageViewDictionary
        NSUInteger existingPageCount = 0;
        for (NSNumber *key in pageViewDictionary) {
            if ([key unsignedIntegerValue] >= existingPageCount) {
                existingPageCount = [key unsignedIntegerValue] + 1;
            }
        }

        for (int i = 0; i < MAX(numberOfPages, existingPageCount); ++i) {
            if (i >= numberOfPages || 
                i < (intSelectedPage - 1) ||
                i > (intSelectedPage + 1)) {
                [self unloadViewForIndex:i];
            } else {
                if (reloadData) {
                    //Unload the view if we're reloading all the data
                    [self unloadViewForIndex:i];
                }
                [self loadViewForIndex:i];
            }
        }

        [reuseViewDictionary removeAllObjects];
    }

    @end

答案 1 :(得分:10)

实际上,通过在UIScrollView上设置分页属性来完成分页位。页面控件只是一个有用的UI构造,但实际上并没有与分页本身做任何事情。

答案 2 :(得分:7)

UIPageControl做了两件事:(1)它显示点,包括当前所选页面的突出显示的点,以及(2)当用户点击它时,它会生成UIControlEventValueChanged事件。点击控件右侧以向右翻页;点击左侧以向左翻页。您应该实现此行为以与HIG保持一致!

要捕获事件,请添加:

[myUiPageControl addTarget:self action:@selector(pageChanged:) forControlEvents:UIControlEventValueChanged];

以及该委托功能:

-(void)pageChanged:(UIPageControl*)thePageControl;

这个名字可以是你想要的;我用“pageChanged”作为例子。回调签名可以是pageChanged,pageChanged:或pageChanged:forEvent:。此回调函数应该导致您的滚动视图(或您有什么)更新。

分页本身通常是通过使用UIScrollView启用分页和隐藏滚动条来完成的。告诉scrollview使用分页和电影逐页神奇地移动;确保捕获该更改以更新UIPageControl的currentPage属性。

答案 3 :(得分:2)

你是对的 - 除了页面底部的点之外,UIPageControl本身不会绘制任何东西;你需要另一种观点来做到这一点。

答案 4 :(得分:1)

要使用Werner Altewischer类,请添加PagedViewDelegate以连接并完成您的课程,如下所示:

@interface ViewController (){
    //header view
    UIPageControl* headPageControl;
    UIScrollView* headScrollView;
    PagedView* headerView;
    NSMutableArray* headerViews;
}
//header view
-(void)initHeader;
-(void)setHeaderViews:(NSMutableArray*)views;
-(void)addHeaderView:(UIView*)view;
-(void)popHeader;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self initHeader];
    [self popHeader];  
}

-(void)initHeader
{
    float frameWidth = self.view.frame.size.width;

    headPageControl = [[UIPageControl alloc]initWithFrame:CGRectMake(0, HEADER_HEIGHT-PAGE_CONTROL_HEIGHT, frameWidth, PAGE_CONTROL_HEIGHT)];
    [headPageControl setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.5]];

    headerViews = [NSMutableArray array];

    headScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, frameWidth, HEADER_HEIGHT)];
    headScrollView.showsHorizontalScrollIndicator = NO;

    headerView = [[PagedView alloc] initWithFrame:CGRectMake(0, 0, frameWidth, HEADER_HEIGHT)];
    headerView.delegate = self;
    headerView.pageControl = headPageControl;
    headerView.scrollView = headScrollView;

    [headerView addSubview:headScrollView];
    [headerView addSubview:headPageControl];

    [headerView setBackgroundColor:[UIColor darkGrayColor]];
    [self.view addSubview:headerView];
}

-(NSUInteger)numberOfPagesInPagedView:(PagedView *)view
{
    //NSLog(@"number of pages %i", headPageControl.numberOfPages);
    return headPageControl.numberOfPages;
}

-(UIView*)pagedView:(PagedView *)view viewForPageAtIndex:(NSUInteger)page
{
    //NSLog(@"open page %i", page);
    return [headerViews objectAtIndex:page];
}

-(void)setHeaderViews:(NSMutableArray*)views
{
    headerViews = views;
    headPageControl.numberOfPages = headerViews.count;
}

-(void)addHeaderView:(UIView*)view
{
    [headerViews addObject:view];
    headPageControl.numberOfPages = headerViews.count;
}

-(void)popHeader
{
    float frameWidth = self.view.frame.size.width;
    CGRect _frame = CGRectMake(0, 0, frameWidth, HEADER_HEIGHT);
    UIView* v = [[UIView alloc] initWithFrame:_frame];
    [v setBackgroundColor:[UIColor greenColor]];
    [self addHeaderView:v];

    UIView* v0 = [[UIView alloc] initWithFrame:_frame];
    [v0 setBackgroundColor:[UIColor purpleColor]];
    [self addHeaderView:v0];

    UIView* v1 = [[UIView alloc] initWithFrame:_frame];
    [v1 setBackgroundColor:[UIColor yellowColor]];
    [self addHeaderView:v1];
}