开头
UIScrollView
实际用处
基础用法
- 使用
UIScrollView有两个需要注意的尺寸自身frame和内容的contentSize
frame指的是UIScrollView的自身位置和大小,理解为一个框,是用户可见的范围
contentSize指的是放入UIScrollView的内容大小,是用户可移动的最大范围
UIScrollView的缩放显示,需要用到代理方法,而代理方法,在使用过程中可以理解为控件的监听方法,当控件在某一个状态中需要调用这个函数内的方法已实现某种需求
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"WechatIMG8793"]]
UIScrollView *scrollView = [UIScrollView new]
self.imageView = imageView
self.scrollView = scrollView
//设置代理
scrollView.delegate = self
scrollView.backgroundColor = [UIColor redColor]
scrollView.frame = [UIScreen mainScreen].bounds
imageView.frame = scrollView.frame
[imageView sizeToFit]
//scrollView的缩放比例
scrollView.maximumZoomScale = 2.0
scrollView.minimumZoomScale = 0.1
//scrollView的内容大小
scrollView.contentSize = imageView.frame.size
//scrollView横竖指示器
scrollView.showsVerticalScrollIndicator = NO
scrollView.showsHorizontalScrollIndicator = NO
[scrollView addSubview:imageView]
[self.view addSubview:scrollView]
- 缩放代理方法,返回需要改变的控件,
UIScrollView会进行根据最大最小缩放比例自动缩放
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
NSLog(@"zooming...");
return self.imgView;
}
- 但是在实际开发中,往往需要图片在屏幕中间位置,就需要对内容坐标进行偏移,就需要在
UIScrollView结束缩放的状态进行操作。函数中的view为scrollView中的内容
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
CGFloat offsetY = (scrollView.bounds.size.height - view.frame.size.height) * 0.5
offsetY = offsetY < 0 ? 0 : offsetY
CGFloat offsetX = (scrollView.bounds.size.width - view.frame.size.width) * 0.5
offsetX = offsetX < 0 ? 0 : offsetX
//设置间距
scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0, 0)
}
图片轮播器
- 使用
UIScrollView实现图片轮播器的思路从以下几个方面考虑
- 如何实现内容,通过图片拼接作为
scrollView内容
- 如何实现轮播,利用
UIScrollView的pagingEnabled进行翻页效果的显示,也就是当内容到达下一个scrollView的自身的范围,会产生翻页的效果
- 如何获取页数,利用
UIpageControl进行页数显示
- 如何实现自动滚动,利用定时器,设置
scrollView偏移量,进行自动滚动
UIScrollView *scrollView = [UIScrollView new]
//指示器
UIPageControl *pageControl = [UIPageControl new]
//指示器的数量
pageControl.numberOfPages = 6
//设置当前的页数
pageControl.currentPage = 0
//指示器的颜色
pageControl.pageIndicatorTintColor = [UIColor redColor]
//指示器当前的颜色
pageControl.currentPageIndicatorTintColor = [UIColor blueColor]
//固定imageView的宽高
CGFloat imgW = 336
CGFloat imgH = 448
//创建6个imageView
for (int i = 0
UIImageView *imageView = [UIImageView new]
NSString *imageName = [NSString stringWithFormat:@"img_%02d", i]
imageView.image = [UIImage imageNamed:imageName]
//计算x坐标
CGFloat imgX = i * imgW
imageView.frame = CGRectMake(imgX, 0, imgW, imgH)
imageView.contentMode = UIViewContentModeScaleAspectFit
//根据x坐标的不同,拼接到scrollView中
[scrollView addSubview:imageView]
}
scrollView.backgroundColor = [UIColor blackColor]
//scrollView的大小,要等于一页的imageView
scrollView.frame = CGRectMake(50, 50, imgW, imgH)
//contentSize的宽度要等一所有imageView合起来的宽度
scrollView.contentSize = CGSizeMake(imgW * 6, 0)
//实现分页效果
scrollView.pagingEnabled = YES
//隐藏滚动指示器
scrollView.showsHorizontalScrollIndicator = NO
//设置代理
scrollView.delegate = self
[self.view addSubview:scrollView]
//页数指示器要添加到主界面上,与scrollView同级,否则会随着内容滚动
pageControl.frame = CGRectMake(100, 498, 200, 20)
[self.view addSubview:pageControl]
self.pageControl = pageControl
self.scrollView = scrollView
- 关于页数获取,在正常使用的时候,用户希望在划动过程中就看到页数的变化,显得不会生硬
UIscrollView偏移量的概念指的是,scrollView的内容移动的位置相对于最开始显示的位置
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
//1.获取当前滚动方向的偏移值
CGFloat offsetX = scrollView.contentOffset.x
//优化,用已经偏移了的值,加上半页的宽度,在切换的过程中,只要拖动了半页,就会使pageControl变化
offsetX = offsetX + (scrollView.frame.size.width * 0.5)
//2. 用x方向的偏移值 / 每一页的宽度,取商,就是当前的页码(索引)
int page = offsetX / scrollView.frame.size.width
self.pageControl.currentPage = page
}
- OC中主要有三种定时器,这里使用
NSTimer,使用scheduledTimerWithTimeInterval...创建的定时器,会自动添加到消息循环中,模式为默认的NSDefaultRunLoopMode
- 利用
pageControl的页数进行偏移量的计算,然后进行设置
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(scrollImage) userInfo:nil repeats:YES];
- (void)scrollImage {
NSInteger page = self.pageControl.currentPage;
if(page == self.pageControl.numberOfPages - 1)
{
page = 0;
}
else
{
page++;
}
CGFloat offsetX = page * self.scrollView.frame.size.width;
[self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
}
- 由于定时器
NSTimer优先级的问题,当使用其他控件的时候,会影响定时器的效果,所以要修改定时器的优先级与控件优先级一致
NSRunLoop *runLoop = [NSRunLoop currentRunLoop]
[runLoop addTimer:self.timer forMode:NSRunLoopCommonModes]
- 而在开始拖动
scrollViewWillBeginDragging时,要将定时器关闭,在结束拖动scrollViewDidEndDragging的时候,重新将定时器打开
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.timer invalidate];
self.timer = nil;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(scrollImage) userInfo:nil repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSRunLoopCommonModes];
}
总结
- 综上,
UIScrollView的使用,需要特别注意一下几个点
- 自身的
frame大小与contentSize大小,前者决定了可见范围,后者决定了可移动的范围
- 偏移值,决定了相对显示的范围
UIScrollView各个状态的代理函数