UIPageControl бесполезен сам по себе? - PullRequest
12 голосов
/ 09 июля 2009

Я пытался использовать UIPageControl для прокручиваемой части приложения, и мне было интересно, как это работает. В документах показаны методы смены страниц, установки количества страниц и т. Д., Но сам по себе элемент управления страницей не охватывает вид прокрутки.

Предполагается, что классы UIPageControl и UIScrollView должны использоваться совместно, когда требуется показать индикатор страницы (как на домашнем экране iPhone со страницами приложения)?

Ответы [ 5 ]

20 голосов
/ 25 октября 2010

Я написал класс (PagedView), который работает так же, как UITableView, и объединяет концепции UIPageControl и UIScrollView способом, используемым, например, на домашнем экране iPhone.

Концепция в основном следующая: вам нужно реализовать PagedViewDelegate, чтобы возвращать количество страниц и представление каждой страницы вашего PagedView. Повторное использование представлений работает так же, как и в UITableView. Используйте конструктор интерфейсов для подключения точек прокрутки и 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
10 голосов
/ 09 июля 2009

Бит пейджинга фактически делается путем установки свойства пейджинга в UIScrollView. Элемент управления страницей - это просто полезная конструкция пользовательского интерфейса, но на самом деле он не имеет ничего общего с самой страницей.

7 голосов
/ 08 июня 2011

UIPageControl выполняет две функции: (1) отображает точки, включая выделенную точку для текущей выбранной страницы, и (2) генерирует событие UIControlEventValueChanged, когда пользователь нажимает на нее. Нажмите на правой стороне элемента управления, чтобы перейти на страницу справа; нажмите на левую сторону, чтобы перейти на страницу слева. Вы должны реализовать это поведение в соответствии с HIG!

Чтобы перехватить событие, добавьте:

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

и эта функция делегата также:

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

Имя может быть любым, что вы хотите; Я использовал "pageChanged", например. Подпись обратного вызова может быть pageChanged, pageChanged: или pageChanged: forEvent :. Эта функция обратного вызова должна вызывать обновление вашего прокрутки (или что у вас).

Пейджинг сам по себе обычно выполняется с помощью UIScrollView с включенным пейджингом и скрытыми полосами прокрутки. Скажите скроллвью использовать пейджинг, и щелчки волшебным образом перемещают страницу за страницей; убедитесь, что вы перехватили это изменение, чтобы обновить свойство currentPage UIPageControl.

2 голосов
/ 09 июля 2009

Вы правы - UIPageControl не рисует ничего, кроме точек внизу страницы; вам нужен другой вид, чтобы сделать это.

1 голос
/ 18 октября 2012

Чтобы использовать класс 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];
}
...