2009-07-09 18 views
12

Szukałem przy użyciu UIPageControl dla przewijanej części aplikacji i zastanawiałem się, jak to działa. Dokumenty przedstawiają metody zmiany stron, ustawiania liczby stron itp., Ale kontrola strony nie obejmuje żadnego widoku przewijania.Czy UIPageControl jest bezużyteczny sam?

Czy należy używać klas UIPageControl i UIScrollView w połączeniu, gdy chce się wyświetlić wskaźnik strony (na przykład na ekranie głównym iPhone'a ze stronami aplikacji)?

Odpowiedz

10

Bit stronicowania jest faktycznie wykonywany przez ustawienie właściwości stronicowania na UIScrollView. Kontrola strony jest po prostu użyteczną konstrukcją UI, ale w rzeczywistości nie ma nic wspólnego z samym stronicowaniem.

2

Masz rację - UIPageControl nie rysuje niczego samodzielnie poza kropkami na dole strony; potrzebujesz innego widoku, aby to zrobić.

20

Napisałem klasę (PagedView), która działa podobnie jak UITableView i scala koncepcje UIPageControl i UIScrollView w sposób stosowany na przykład na ekranie głównym iPhone'a.

Koncepcja jest zasadniczo następująca: należy zaimplementować PagedViewDelegate, aby zwrócić liczbę stron i widok dla każdej strony z Państwa PagedView. Ponowne użycie widoków działa tak samo, jak w widoku UITableView. Użyj narzędzia do budowania interfejsów, aby podłączyć punkty przewijania i pageControl.

Proszę dać mi znać, jeśli uznają Państwo tę klasę za przydatną.

.h-file:

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

// 
// 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: Czy możesz expalin jaki sposób mogę korzystać z tej klasy? –

+0

Cześć Werner, czy możesz podać proste użycie tej klasy jako przykładu? Być może zechcesz opublikować go na githubie. – ardochhigh

+0

Aby skorzystać z tego, wystarczy dodać do Your ViewController dwie metody: – HotJard

7

UIPageControl robi dwie rzeczy: (1) wyświetla kropki, w tym podświetlonej kropki dla aktualnie wybranej strony, i (2) generuje zdarzenie UIControlEventValueChanged, gdy użytkownik dotknie go. Stuknij po prawej stronie kontrolki, aby strona była po prawej; dotknij po lewej stronie, aby strona po lewej stronie. Musisz powinien wdrożyć to zachowanie, aby być zgodne z HIG!

do pułapki zdarzenie, należy dodać:

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

i tę funkcję delegata, a także:

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

Nazwa może być cokolwiek chcesz; Użyłem na przykład "pageChanged". Sygnatura zwrotna może być pageChanged, pageChanged: lub pageChanged: forEvent :. Ta funkcja wywołania zwrotnego powinna spowodować aktualizację twojego przewijania (lub tego, co masz).

Przywoływanie samo w sobie jest zwykle wykonywane przy użyciu UIScrollView z włączoną obsługą stronicowania i ukrytymi pasami przewijania. Powiedz przewijaniu, aby używał stronicowania, a kliknięcia magicznie poruszają się strona po stronie; upewnij się, że zatrzymałeś tę zmianę, aby zaktualizować właściwość currentPage modułu UIPageControl.

1

Aby korzystać Werner klasa Altewischer dodać PagedViewDelegate interfejs i zakończyć swoją klasę, jak pokazano poniżej:

@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]; 
} 
Powiązane problemy