iOS中具有图片类的app通常都会有滑动浏览的功能,许多app第一次启动时,也会用UIScrollView+UIPageControl来展示新功能。今天探索一下如何实现该功能。
首先介绍下UIScrollView, UIScrollView中有个重要的属性是contentSize,用于界定滑动范围的大小。UIScrollView本身frame是我们在屏幕上可视部分,也就是说contentSize的宽要大于UIScrollView.frame.size.width才能实现滑动浏览的功能。
另外,图片浏览,为了避免一开始就load所有的UIImageView,可以选择仅仅load当前浏览页面及前后三个UIImageView。而这之外的page上的子视图我们都设置为[NSNull null]。我们在检测到滑动后,再lazy load 所需的UIImageView。
#import "ViewController.h"
@interface ViewController () <UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIPageControl *pageControl;
@property (nonatomic, strong) NSArray *pageImages;
@property (nonatomic, strong) NSMutableArray *pageViews;
- (void)loadVisiblePages;
- (void)loadPage:(NSInteger)page;
- (void)purgePage:(NSInteger)page;
@end
@implementation ViewController
@synthesize scrollView;
@synthesize pageControl;
@synthesize pageImages;
@synthesize pageViews;
- (void)viewDidLoad {
[super viewDidLoad];
// 1
pageImages = [NSArray arrayWithObjects:[UIImage imageNamed:@"2.jpg"],
[UIImage imageNamed:@"5.jpg"],[UIImage imageNamed:@"2.jpg"], [UIImage imageNamed:@"5.jpg"],nil];
NSInteger pageCount = pageImages.count;
pageViews = [[NSMutableArray alloc]init];
for (NSInteger i=0; i<pageCount; i++) {
[self.pageViews addObject:[NSNull null]];
}
// 2
self.scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 568)];
[self.view addSubview:scrollView];
scrollView.delegate = self;
self.pageControl = [[UIPageControl alloc]initWithFrame:CGRectMake(0, 400, 320, 20)];
self.pageControl.currentPage = 0;
[self.pageControl setNumberOfPages:pageCount];
[pageControl setBackgroundColor:[UIColor grayColor]];
[self.view addSubview:pageControl];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
CGSize pagesScrollViewSize = self.scrollView.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageImages.count, pagesScrollViewSize.height);
[self loadVisiblePages];
}
- (void)loadVisiblePages {
CGFloat pageWidth = scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x*2.0f+pageWidth)/(pageWidth*2.0f));
pageControl.currentPage = page;
NSInteger firstPage = page - 1;
NSInteger lastPage = page + 1;
// Pure anything before the first page
for (NSInteger i = 0; i< firstPage; i++) {
[self purgePage:i];
}
// Load pages in our range
for (NSInteger i = firstPage; i<=lastPage; i++) {
[self loadPage:i];
}
// Purge anything after last page
for (NSInteger i = lastPage+1; i<self.pageImages.count; i++) {
[self purgePage:i];
}
}
- (void)loadPage:(NSInteger)page {
if (page<0 || page>=self.pageImages.count) {
return;
}
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull *)pageView == [NSNull null]) {
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
UIImageView *imageView = [[UIImageView alloc]initWithImage:[self.pageImages objectAtIndex:page]];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.frame = frame;
[self.scrollView addSubview:imageView];
[self.pageViews replaceObjectAtIndex:page withObject:imageView];
}
}
- (void)purgePage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what you have to display, then do nothing
return;
}
// Remove a page from the scroll view and reset the container array
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView != [NSNull null]) {
[pageView removeFromSuperview];
[self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
}
}
#pragma mark - Scroll View delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self loadVisiblePages];
}
几个注解:
-判断当前页面是第几个页面时,我们通过UIScrollView.contentOffset.x和pageWidth来判断,这里有一点数学上的运算。
-为了监测scrollView滑动的变化,设置scrollView的delegate,并且实现delegate中scrollViewDidScroll:方法。