2009-07-09 3 views
12

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

Являются ли классы UIPageControl и UIScrollView предполагаемыми для совместного использования, когда вы хотите показать индикатор страницы (например, на главном экране iPhone со страницами приложений)?

ответ

10

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

2

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

20

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

Концепция в основном заключается в следующем: вам нужно реализовать PagedViewDelegate, чтобы вернуть количество страниц и представление для каждой страницы PagedView. Повторное использование просмотров работает так же, как в UITableView. Используйте конструктор интерфейса для подключения точек прокрутки и страницы.

Пожалуйста, дайте мне знать, если вы найдете этот класс полезным.

.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 
+0

@Warner: Можете ли вы expalin, как я могу использовать этот класс? –

+0

Привет, Вернер, можете ли вы предоставить простой пример использования этого класса? Возможно, вы захотите опубликовать его на github. – ardochhigh

+0

Чтобы использовать это, просто добавьте в свой ViewController два метода: – HotJard

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, чтобы использовать пейджинг и щелчки волшебным образом перемещать страницу за страницей; убедитесь, что вы уловили это изменение, чтобы обновить свойство currentPage UIPageControl.

1

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