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
@Warner: Pouvez-vous s'il vous plaît expalin comment je peux utiliser cette classe? –
Bonjour Werner, pouvez-vous fournir un exemple simple en utilisant cette classe? Peut-être que vous pourriez vouloir le poster sur github. – ardochhigh
Pour l'utiliser il suffit d'ajouter à votre ViewController deux méthodes: – HotJard