2009-07-09 7 views
12

Je cherchais à utiliser UIPageControl pour faire défiler une application, et je me demandais comment cela fonctionnait. Les docs montrent des méthodes pour changer de page, régler le nombre de pages etc., mais en soi le contrôle de page n'inclut aucun type d'affichage de défilement.UIPageControl est-il inutile?

Les classes UIPageControl et UIScrollView sont-elles supposées être utilisées conjointement lorsque l'on souhaite afficher l'indicateur de page (comme sur l'écran d'accueil de l'iPhone avec les pages de l'application)?

Répondre

10

Le bit de pagination est réellement effectué en définissant la propriété de pagination sur UIScrollView. Le contrôle de page est simplement une construction d'interface utilisateur utile, mais ne fait rien en fait avec la pagination elle-même.

2

Vous avez raison - UIPageControl ne dessine rien d'autre que les points au bas de la page; vous avez besoin d'une autre vue pour le faire.

20

J'ai écrit une classe (PagedView) qui fonctionne comme UITableView et fusionne les concepts de UIPageControl et UIScrollView d'une manière utilisée par exemple sur l'écran d'accueil de l'iPhone.

Le concept est essentiellement le suivant: vous devez implémenter PagedViewDelegate pour renvoyer le nombre de pages et une vue pour chaque page de votre PagedView. La réutilisation des vues fonctionne de la même manière que dans UITableView. Utilisez le constructeur d'interface pour connecter les prises scrollview et pageControl.

Faites-moi savoir si vous trouvez ce cours utile.

.h fichier:

// 
// 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 fichier:

// 
// 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: Pouvez-vous s'il vous plaît expalin comment je peux utiliser cette classe? –

+0

Bonjour Werner, pouvez-vous fournir un exemple simple en utilisant cette classe? Peut-être que vous pourriez vouloir le poster sur github. – ardochhigh

+0

Pour l'utiliser il suffit d'ajouter à votre ViewController deux méthodes: – HotJard

7

UIPageControl fait deux choses: (1) il affiche des points, y compris un point mis en évidence pour la page sélectionnée, et (2) il génère un événement UIControlEventValueChanged lorsque l'utilisateur appuie dessus. Appuyez sur le côté droit du contrôle pour faire une recherche vers la droite; appuyez sur le côté gauche pour faire défiler la page vers la gauche. Vous devrait mettre en œuvre ce comportement pour être cohérent avec le HIG!

Pour piéger l'événement, ajouter:

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

et que la fonction de délégué ainsi:

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

Le nom peut être tout ce que vous voulez; J'ai utilisé "pageChanged" par exemple. La signature de rappel peut être pageChanged, pageChanged: ou pageChanged: forEvent :. Cette fonction de rappel devrait provoquer la mise à jour de votre scrollview (ou ce que vous avez).

La pagination, elle-même, est généralement effectuée à l'aide d'UIScrollView avec pagination activée et barres de défilement masquées. Dites au scrollview d'utiliser la pagination et déplacez les puces magiquement, page par page; assurez-vous de capturer cette modification pour mettre à jour la propriété currentPage de UIPageControl.

1

Pour utiliser la classe Werner Altewischer ajouter PagedViewDelegate à l'interface et compléter votre classe comme indiqué ci-dessous:

@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]; 
} 
Questions connexes