2009-07-09 12 views
12

Ich habe mit der UIPageControl für einen Scroll-Teil einer Anwendung untersucht, und ich habe mich gefragt, wie es funktioniert. Die Dokumente zeigen Methoden zum Ändern von Seiten, Festlegen der Anzahl von Seiten usw., aber die Seitensteuerung umfasst selbst keine Art von Bildlaufansicht.Ist UIPageControl von selbst nutzlos?

Sollen die UIPageControl- und UIScrollView-Klassen zusammen verwendet werden, wenn der Seitenindikator angezeigt werden soll (wie auf dem Startbildschirm des iPhone mit den App-Seiten)?

Antwort

10

Das Paging-Bit wird tatsächlich ausgeführt, indem die Paging-Eigenschaft auf UIScrollView festgelegt wird. Die Seitenkontrolle ist einfach ein nützliches UI-Konstrukt, hat aber nichts mit dem Paging selbst zu tun.

2

Sie haben Recht - UIPageControl zeichnet selbst nichts anderes als die Punkte am unteren Rand der Seite; Sie brauchen eine andere Ansicht, um das zu tun.

20

Ich habe eine Klasse (PagedView) geschrieben, die genau wie UITableView funktioniert und die Konzepte von UIPageControl und UIScrollView in einer Weise kombiniert, die zum Beispiel auf dem iPhone-Startbildschirm verwendet wird.

Das Konzept ist grundsätzlich wie folgt: Sie müssen PagedViewDelegate implementieren, um die Anzahl der Seiten und eine Ansicht für jede Seite von PagedView zurückzugeben. Die Wiederverwendung von Ansichten funktioniert genauso wie in UITableView. Verwenden Sie den Schnittstellen-Builder, um die Scrollview- und pageControl-Anschlüsse zu verbinden.

Bitte lassen Sie mich wissen, wenn Sie diese Klasse nützlich finden.

.h-Datei:

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

// 
// 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 : Können Sie bitte expalin, wie ich diese Klasse benutzen kann? –

+0

Hallo Werner, kannst du eine einfache Verwendung dieser Klasse als Beispiel bieten? Vielleicht möchten Sie es auf GitHub veröffentlichen. – ardochhigh

+0

Um dies zu verwenden, fügen Sie Ihrem ViewController zwei Methoden hinzu: – HotJard

7

UIPageControl macht zwei Dinge: (1) zeigt es Punkte, darunter einen markierten Punkt für die aktuell ausgewählte Seite, und (2) es erzeugt ein UIControlEventValueChanged-Ereignis, wenn der Benutzer darauf tippt. Tippen Sie auf die rechte Seite des Steuerelements, um nach rechts zu blättern. Tippen Sie auf die linke Seite, um nach links zu blättern. Sie sollten implementieren dieses Verhalten im Einklang mit der HIG sein!

um das Ereignis zu Trap hinzu:

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

und dass Delegatfunktion auch:

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

Der Name kann alles sein, was Sie wollen; Ich habe zum Beispiel "pageChanged" verwendet. Die Callback-Signatur kann pageChanged, pageChanged: oder pageChanged sein: forEvent :. Diese Callback-Funktion sollte Ihre Scrollview (oder was haben Sie) zu aktualisieren.

Das Paging selbst wird normalerweise mit einem UIScrollView ausgeführt, bei dem Paging aktiviert und Bildlaufleisten ausgeblendet sind. Sagen Sie der Bildlaufansicht, dass Seitenwechsel und Flicks auf magische Weise Seite für Seite verschoben werden sollen. Stellen Sie sicher, dass Sie diese Änderung erfassen, um die currentPage-Eigenschaft von UIPageControl zu aktualisieren.

1

Um Werner Altewischer-Klasse verwenden PagedViewDelegate fügen Sie Ihre Klasse als Schnittstelle und zu vervollständigen, wie unten dargestellt:

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