Paging-enabled UIScrollView
UIPageControl与启用Page的UIScrollView经常结合使用用于浏览图片。
本文介绍一些使用UIPageControl和UIScrollView的开源代码。
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
- (void)loadScrollViewWithPage:(int)page
{
if (page < 0)
return;
if (page >= kNumberOfPages)
return;
// replace the placeholder if necessary
MyViewController *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null])
{
controller = [[MyViewController alloc] initWithPageNumber:page];
[viewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}
// add the controller's view to the scroll view
if (controller.view.superview == nil)
{
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];
NSDictionary *numberItem = [self.contentList objectAtIndex:page];
controller.numberImage.image = [UIImage imageNamed:[numberItem valueForKey:ImageKey]];
controller.numberTitle.text = [numberItem valueForKey:NameKey];
}
}
[pageControl addTarget:self action:@selector(changePage:) forControlEvents:UIControlEventValueChanged];
- (IBAction)changePage:(id)sender
{
int page = pageControl.currentPage;
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
// update the scroll view to the appropriate page
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
[scrollView scrollRectToVisible:frame animated:YES];
}
核心代码:
PhoneContentController.h
PhoneContentController.m
工程代码:PageControl.zip
AFImageViewer是由UIScrollView和UIPageControl组成的视图框架,用于图片浏览,其对苹果的PageControl例子进行了扩展,支持三种获取需显示图片的方式。
self.imageViewer.imagesUrls = [self imageUrls];
self.imageViewer.contentMode = UIViewContentModeScaleAspectFill;
self.imageViewer.loadingImage = [UIImage imageNamed:@"dark_blue.jpg"];
self.imageViewer.tempDownloadedImageSavingEnabled = YES;
self.imageViewer.images = [self images];
self.imageViewer.contentMode = UIViewContentModeScaleAspectFit;
[self.imageViewer setContentMode:UIViewContentModeScaleAspectFill];
self.imageViewer.delegate = self;
-(int)numberOfImages
{
return num;
}
-(UIImageView *)imageViewForPage:(int)page
{
...
return imgView;
}
核心代码:
AFImageViewer.h
AFImageViewer.m
工程代码:https://github.com/AdrianFlorian/AFImageViewer
在App Store中浏览程序图片时,在当前图片两侧可看到之前和之后图片的一部分,让用户得知之前或之后还有内容。
实现这种效果的方法是将UIScrollView的frame宽度缩小,使之小于screen的宽度,并将clipsToBounds设为NO,这样在UIScrollView当前Frame两侧的内容也可显示出来。
这样存在一个问题,UIScrollView当前Frame两侧的内容不响应拖动事件,解决方法时,将UIScrollView嵌入于一个UIView中,而此UIView的宽度为Screen的宽度,然后重写UIView的hitTest方法,当点击的点在UIView内时,hitTest返回UIScrollView。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if ([self pointInside:point withEvent:event]) {
return _scrollView;
}
return nil;
}
代码:https://github.com/alexrepty/Paging-Enabled-UIScrollView-With-Previews
BSPreviewScrollView对Paging-enabled UIScrollView With Previews中代码进行封装和扩展,将UIScrollView封装在其中,统一处理UIScrollView的各种事件。Paging-enabled UIScrollView With Previews中的hitTest方法总是返回UIScrollView对象,从而使UIScrollView内部视图的点击/触摸事件无法响应。这里修改如下:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// If the point is not inside the scrollview, ie, in the preview areas we need to return
// the scrollview here for interaction to work
if (!CGRectContainsPoint(scrollView.frame, point)) {
return self.scrollView;
}
// If the point is inside the scrollview there's no reason to mess with the event.
// This allows interaction to be handled by the active subview just like any scrollview
return [super hitTest:point withEvent:event];
}
在hitTest方法,仅在点击位置在UIScrollView之外时才返回UIScrollView对象,这样点击在UIScrollView内部时,就可以将点击/触摸事件传递给UIScrollView的子视图。
类似App Strore中图片两边的空白间隙需要用户自己处理,即要显示的图片要比UIScrollView的frame宽度略小些。
核心代码:
BSPreviewScrollView.h
BSPreviewScrollView.m
苹果公司的PageControl示例代码为每个要显示的页都创建一个视图控制器,Matt Gallagher讲述了一个方法用两个实际的视图控制器模拟多个页显示的方法。其核心思想是,保存两个内容视图控制器:currentPage和nextPage,currentPage为当前显示的页,当向右滑动时,更新nextPage的内容为下一页内容,并放在UIScrollView的对应位置上;当向左滑动时,更新nextPage的内容为前一页内容,并放置在UIScrollView前一页的位置上。此方法应用的场景应该时,重新load数据时速度比较快,不然显示就会很缓慢,影响平滑滑动的效果。
代码中奇怪的是,在启动时会自动滑至第2页,在滑动过程中并没有完整按页显示,在内容中还会显示之前页的部分内容,滑动还有反弹效果,还没看明白是哪里的问题。
核心代码:
PagingScrollViewController.h
PagingScrollViewController.m
参考:
UIPageControl Class Reference
UIScrollView Class Reference
PageControl 苹果示例代码
AFImageViewer
Paging-enabled UIScrollView With Previews
iPhone/iPad – AppStore like UIScrollView with paging and preview
Multiple virtual pages in a UIScrollView with just 2 child views
原文地址:http://www.winddisk.com/2012/06/11/paging-enabled-uiscrollview/
优质内容筛选与推荐>>