版本
Xcode 9.1
一、纯代码创建
1. 简单使用
首先,定义一个UIScrollView类型的属性:
@property (nonatomic, strong) UIScrollView *scrollView;
然后在懒加载(getter方法)里设置scrollView相关属性:
#define SCROLL_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCROLL_HEIGHT [UIScreen mainScreen].bounds.size.height/3
#pragma mark - 懒加载
- (UIScrollView *)scrollView {
if (_scrollView == nil) {
// 实例化
_scrollView = [[UIScrollView alloc] init];
// 设置尺寸大小
_scrollView.frame = CGRectMake(, , SCROLL_WIDTH, SCROLL_HEIGHT);
// 设置滚动区域
_scrollView.contentSize = CGSizeMake(SCROLL_WIDTH*, SCROLL_HEIGHT);
// 隐藏水平滑条
_scrollView.showsHorizontalScrollIndicator = NO;
// 设置分页(每次滑动一页)
_scrollView.pagingEnabled = YES;
// 弹簧效果(边界拉出来一小段会弹回去)
_scrollView.bounces = NO; //关闭
}
return _scrollView;
}
然后就可以在viewDidLoad或者其他地方调用scrollView了:
- (void)viewDidLoad {
[super viewDidLoad];
// 实例化3个UIImageView,并添加到scrollView
for(int i=; i<; i++) {
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(SCROLL_WIDTH*i, , SCROLL_WIDTH, SCROLL_HEIGHT);
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i]];
// 将imageView添加到scrollView
[self.scrollView addSubview:imageView];
}
// 添加scrollView到self.view
[self.view addSubview:self.scrollView];
}
效果图:
2. 实现图片循环切换
先来讲讲思路:
如下图,我们要实现三张图片的循环切换。
首先,我们设置五个视图,第一个视图显示最后一张图片,最后一个视图显示第一张图片。
然后,设置scrollView的初始偏移量为第二个视图。
最后,设置代理,在滑动结束的代理方法中,(悄悄地)将试图1切换到视图4,亦或将视图5切换到视图2。
完整代码如下:
#define SCROLL_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCROLL_HEIGHT [UIScreen mainScreen].bounds.size.height/3
#import "ViewController.h"
@interface ViewController () <UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *scrollView;
@end
@implementation ViewController
#pragma mark - 生命周期
- (void)viewDidLoad {
[super viewDidLoad];
// 实例化5个UIImageView,并添加到scrollView
for(int i=; i<; i++) {
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(SCROLL_WIDTH*i, , SCROLL_WIDTH, SCROLL_HEIGHT);
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i]];
if (i == ) {
// 第一个视图显示最后一张图片
imageView.image = [UIImage imageNamed:@"2.jpg"];
}else if(i == ){
// 第五个视图显示第一张图片
imageView.image = [UIImage imageNamed:@"0.jpg"];
}else {
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i-]];
}
// 添加imageView到scrollView
[self.scrollView addSubview:imageView];
}
// 添加scrollView到self.view
[self.view addSubview:self.scrollView];
}
#pragma mark - UIScrollViewDelegate
// 已经停止减速
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
// 改变偏移量
if (scrollView.contentOffset.x >= SCROLL_WIDTH*) {
// 移动到第一个视图
scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*, );
}else if(scrollView.contentOffset.x <= ){
// 移到第三个视图
scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*, );
}
}
#pragma mark - 懒加载
- (UIScrollView *)scrollView {
if (_scrollView == nil) {
// 实例化
_scrollView = [[UIScrollView alloc] init];
// 设置尺寸大小
_scrollView.frame = CGRectMake(, , SCROLL_WIDTH, SCROLL_HEIGHT);
// 设置滚动区域
_scrollView.contentSize = CGSizeMake(SCROLL_WIDTH*, SCROLL_HEIGHT);
// 隐藏水平滑条
_scrollView.showsHorizontalScrollIndicator = NO;
// 设置分页(每次滑动一页)
_scrollView.pagingEnabled = YES;
// 弹簧效果(边界拉出来一小段会弹回去)
_scrollView.bounces = NO; //关闭
_scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*, );
// 设置代理方法
_scrollView.delegate = self;
}
return _scrollView;
}
效果:
3. UIScrollView搭配UIPageControl
实现的效果如下:定时每3秒钟自动向后翻一页。当开始有手指拖拽时,定时暂停;直到松开手指视图滑动结束后,才重新3秒定时。
只需在如上的代码添加一个UIPageControl用于小点点显示当前页数,和添加一个定时器NSTimer用于定时切换。
完整代码:
#define SCROLL_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCROLL_HEIGHT [UIScreen mainScreen].bounds.size.height/3
#import "ViewController.h"
@interface ViewController () <UIScrollViewDelegate> {
NSTimer *_timer;
}
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIPageControl *pageControl;
@end
@implementation ViewController
#pragma mark - 生命周期
- (void)viewDidLoad {
[super viewDidLoad];
// 实例化5个UIImageView,并添加到scrollView
for(int i=; i<; i++) {
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(SCROLL_WIDTH*i, , SCROLL_WIDTH, SCROLL_HEIGHT);
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i]];
if (i == ) {
// 第一个视图显示最后一张图片
imageView.image = [UIImage imageNamed:@"2.jpg"];
}else if(i == ){
// 第五个视图显示第一张图片
imageView.image = [UIImage imageNamed:@"0.jpg"];
}else {
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i-]];
}
// 添加imageView到scrollView
[self.scrollView addSubview:imageView];
}
// 添加scrollView到self.view
[self.view addSubview:self.scrollView];
// 添加pageControl到self.view
[self.view addSubview:self.pageControl];
// 启动定时器
_timer = [NSTimer scheduledTimerWithTimeInterval: target:self selector:@selector(changeImage:) userInfo:nil repeats:YES];
}
#pragma mark - UIScrollViewDelegate
// 准备开始滑动 (仅手动拖拽时调用;代码设置setContentOffset:/scrollRectToVisible:不会调用)
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[_timer setFireDate:[NSDate distantFuture]]; // 很久之后才触发,相当于暂停
}
// 已经停止减速(仅手动拖拽时调用)
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
_timer.fireDate = [NSDate dateWithTimeInterval: sinceDate:[NSDate date]];
[self updateContentOffsetAndCurrentPage];
}
#pragma mark - 私有方法
// 定时3秒时间到,开始切换图片
- (void)changeImage:(NSTimer *)timer {
CGPoint tempPoint = self.scrollView.contentOffset;
tempPoint.x += SCROLL_WIDTH;
if (tempPoint.x/SCROLL_WIDTH >= ) {
tempPoint.x = ;
}
self.scrollView.contentOffset = tempPoint;
[self updateContentOffsetAndCurrentPage];
}
// 更新当前图片和页数
- (void)updateContentOffsetAndCurrentPage {
// 更新偏移量
if (self.scrollView.contentOffset.x >= SCROLL_WIDTH*) {
// 移动到第一个视图
self.scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*, );
}else if(self.scrollView.contentOffset.x <= ){
// 移到第三个视图
self.scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*, );
}
// 更新当前页数
NSInteger currentPage = (self.scrollView.contentOffset.x-SCROLL_WIDTH)/SCROLL_WIDTH;
if (currentPage < ) {
currentPage = ;
}else if (currentPage > ) {
currentPage = ;
}
self.pageControl.currentPage = currentPage;
}
#pragma mark - 懒加载
- (UIScrollView *)scrollView {
if (_scrollView == nil) {
// 实例化
_scrollView = [[UIScrollView alloc] init];
// 设置尺寸大小
_scrollView.frame = CGRectMake(, , SCROLL_WIDTH, SCROLL_HEIGHT);
// 设置滚动区域
_scrollView.contentSize = CGSizeMake(SCROLL_WIDTH*, SCROLL_HEIGHT);
// 隐藏水平滑条
_scrollView.showsHorizontalScrollIndicator = NO;
// 设置分页(每次滑动一页)
_scrollView.pagingEnabled = YES;
// 弹簧效果(边界拉出来一小段会弹回去)
_scrollView.bounces = NO; //关闭
_scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*, );
// 设置代理方法
_scrollView.delegate = self;
}
return _scrollView;
}
- (UIPageControl *)pageControl {
if (_pageControl == nil) {
// 实例化UIPageControl
_pageControl = [[UIPageControl alloc] init];
_pageControl.frame = CGRectMake(, +SCROLL_HEIGHT-, SCROLL_WIDTH, );
// 设置总页数
_pageControl.numberOfPages = ;
// 设置背景色
_pageControl.backgroundColor = [UIColor clearColor];
// 设置当前页颜色
_pageControl.currentPageIndicatorTintColor = [UIColor purpleColor];
// 设置其他页颜色
_pageControl.pageIndicatorTintColor = [UIColor greenColor];
//添加事件
// [_pageControl addTarget:self action:@selector(pageDidChanged:) forControlEvents:UIControlEventValueChanged];
}
return _pageControl;
}
@end
4. 使用UIScrollView实现图片缩放功能
首先,设置滚动区域足够大,并设置缩放比例范围:
// 设置滚动区域
_scrollView.contentSize = CGSizeMake(SCROLL_WIDTH*, SCROLL_HEIGHT*);
_scrollView.minimumZoomScale = ; // 最小缩小比例
_scrollView.maximumZoomScale = ; // 最大放大比例
然后在scrollView里添加图片:
UIImage *image = [UIImage imageNamed:@"1.jpg"];
_imageView = [[UIImageView alloc] initWithImage:image];
[self.scrollView addSubview:_imageView];
最后在代理方法里返回需要放大的控件:
// 缩放代理方法:返回需要缩放的视图 (手动拖拽及代码设置缩放均会调用)
- (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return _imageView;
}
接下来,可用手指捏合图片或者调用setZoomScale:animated:/zoomToRect:animated:方法来触发以下代理方法执行进一步操作:
// 准备开始缩放 (手动拖拽及代码设置均会调用)
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view NS_AVAILABLE_IOS(_2) {
NSLog(@"%s",__func__);
}
// 正在缩放 (手动拖拽及代码设置均会调用,可能多次调用)
- (void)scrollViewDidZoom:(UIScrollView *)scrollView NS_AVAILABLE_IOS(_2) {
NSLog(@"%s",__func__);
}
// 已结束缩放 (手动拖拽及代码设置均会调用)
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale {
NSLog(@"%s",__func__);
}
5. UIScrollView的代理方法总结
// 准备开始滑动 (仅手动拖拽时调用;代码设置setContentOffset:/scrollRectToVisible:不会调用)
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
// 已经开始滑动(手动拖拽及代码设置滚动均会调用,可能多次调用)
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
// 准备结束滑动(仅手动拖拽时调用)
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset NS_AVAILABLE_IOS(_0);
// 已经结束滑动(仅手动拖拽时调用)
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
// 准备开始减速(仅手动拖拽时调用)
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;
// 已经停止减速(仅手动拖拽时调用)
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
// 滚动完毕(代码设置setContentOffset/scrollRectVisible:animated:,且animated设为YES时才调用)
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;
// 缩放代理方法:返回需要缩放的视图 (手动拖拽及代码设置均会调用)
- (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
// 准备开始缩放 (手动拖拽及代码设置均会调用)
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view NS_AVAILABLE_IOS(_2);
// 正在缩放 (手动拖拽及代码设置均会调用,可能多次调用)
- (void)scrollViewDidZoom:(UIScrollView *)scrollView NS_AVAILABLE_IOS(_2);
// 已结束缩放 (手动拖拽及代码设置均会调用)
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale;
// 是否能滚动到顶端 (当手指触摸状态栏的时候)
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;
// 已经完成滚动到顶端 (触摸状态栏顶端时调用)
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;
// adjustedContentInset(与边缘的距离)值被改变的delegate
- (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView API_AVAILABLE(ios(), tvos());
二、使用XIB与storyboard创建
和UIView的创建差不多,就多了个delegate的关联,就不浪费时间贴上了。可参阅之前的博文:http://www.jianshu.com/p/9362d0274ed5。