1.设置一个ScrollView–ContentSize
#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIImageView *imgView;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  //告诉scrollView,存在与UIScrollView里面的内容的实际大小
  //设置UIScrollView的内容大小等于图片框的实际大小
  //self.scrollView.contentSize=self.imgView.frame.size;
  //也可以设置为图片框图片的大小
  self.scrollView.contentSize=self.imgView.image.size;
}
@end
2.设置一个ScrollView–contentOffset
#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIImageView *imgView;
- (IBAction)scroll;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  //告诉scrollView,存在与UIScrollView里面的内容的实际大小
  //设置UIScrollView的内容大小等于图片框的实际大小
  //self.scrollView.contentSize=self.imgView.frame.size;
  //也可以设置为图片框图片的大小
  self.scrollView.contentSize=self.imgView.image.size;
  //隐藏滚动指示器
  self.scrollView.showsVerticalScrollIndicator=NO;
  self.scrollView.showsHorizontalScrollIndicator=NO;
}

//通过代码来让图片滚动
- (IBAction)scroll {
  //不能直接修改结构体的值,一定要中转一下
  CGPoint point=self.scrollView.contentOffset;
  point.x+=150;
  point.y+=150;
  //直接修改offset没有动画效果
  //self.scrollView.contentOffset=point;
  //通过block块来实现动画效果
  [UIView animateWithDuration:1 animations:^{
    self.scrollView.contentOffset=point;
  }];
  
  //直接使用动画方式来设置
  [self.scrollView setContentOffset:point animated:YES];

}
@end

在这里插入图片描述

3.设置一个ScrollView–contentInset(内容边距)

```objectivec
#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIImageView *imgView;
- (IBAction)scroll;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  //告诉scrollView,存在与UIScrollView里面的内容的实际大小
  //设置UIScrollView的内容大小等于图片框的实际大小
  self.scrollView.contentSize=self.imgView.frame.size;
  //也可以设置为图片框图片的大小
  //self.scrollView.contentSize=self.imgView.image.size;
  
  //隐藏滚动指示器
  self.scrollView.showsVerticalScrollIndicator=NO;
  self.scrollView.showsHorizontalScrollIndicator=NO;
  
  //设置内容的内边距
  self.scrollView.contentInset=UIEdgeInsetsMake(50, 60, 49, 50);
}

//通过代码来让图片滚动
- (IBAction)scroll {
  //不能直接修改结构体的值,一定要中转一下
  CGPoint point=self.scrollView.contentOffset;
  point.x+=0;
  point.y+=0;
  //直接修改offset没有动画效果
  //self.scrollView.contentOffset=point;
  //通过block块来实现动画效果
  [UIView animateWithDuration:1 animations:^{
    self.scrollView.contentOffset=point;
  }];
  
  //直接使用动画方式来设置
  [self.scrollView setContentOffset:point animated:YES];
  
}
@end

在这里插入图片描述

4.喜马拉雅案例综合演示UIScrollView
#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIImageView *lastImageView;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  CGFloat maxH=CGRectGetMaxY(self.lastImageView.frame);
  //设置UIScrollView的contentSize
  self.scrollView.contentSize=CGSizeMake(0, maxH);
  //设置默认滚动位置
  self.scrollView.contentOffset=CGPointMake(0, 120);
  //设置距离上边始终有120的内边距
  self.scrollView.contentInset=UIEdgeInsetsMake(-120, 0, 0, 0);
}
@end

在这里插入图片描述

5.通过代理注册事件

方法步骤
1、设置UIScrollView的delegate属性(也就是为UIScrollView找一个代理对象)
2、让代理对象遵守UIScrollViewDelegate这个协议,当代理对象遵守完毕这个协议以后,就可以保证代理对象中具有了对应的方法
3、当UIScrollView的某个事件被触发的时候,UIScrollView会自动调用代理对象(delegate)的某个方法,并调用这个方法。(这样就实现了事件的机制)

4、我们要做的就是在代理对象的相应方法中编写我们的代码,然后当UIScrollView的某个事件被触发的时候,就会自动的执行这里的代码。

UIScrollView的代理对象是如何工作的
在这里插入图片描述
具体的实现步骤
需求:监听UIScrollView的滚动事件
分析:要监听UIScrollView的滚动事件,需要通过代理来实现,无法通过addTarget方法

通过代理监听滚动事件的步骤
1、为UIScrollView找一个代理对象,也就是设置UIScrollView的delegate属性
2、为了保证代理对象中拥有对应方法,所以必须让代理对象(控制器自己)遵守对应控件的代理协议(当前控制器要作为那个控件的代理对象,就那么控制器就要遵守这个控件的代理协议),一般控件的代理协议命名规则都是:控件名Delegate(如:UIScrollViewDelegate,UIAlertViewDelegate)
3、在控制器中实现所需要的方法

#import "ViewController.h"
//让控制器遵守UIScrollView的代理协议
@interface ViewController ()<UIScrollViewDelegate>

@property (weak, nonatomic) IBOutlet UIScrollView *scrollview;
@property (weak, nonatomic) IBOutlet UIImageView *imgView;

@end
/**
 需求:监听UIScrollView的滚动事件
 分析:要监听UIScrollView的滚动事件,需要通过代理来实现,无法通过addTarget方法
 
 通过代理监听滚动事件的步骤
 1、为UIScrollView找一个代理对象,也就是设置UIScrollView的delegate属性
 2、为了保证代理对象中拥有对应方法,所以必须让代理对象(控制器自己)遵守对应控件的代理协议(当前控制器要作为那个控件的代理对象,就那么控制器就要遵守这个控件的代理协议),一般控件的代理协议命名规则都是:控件名Delegate(如:UIScrollViewDelegate,UIAlertViewDelegate)
 3、在控制器中实现所需要的方法
 */
@implementation ViewController

//即将开始拖拽
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
  NSLog(@"即将开始拖拽");

}

//正在滚动
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
  NSLog(@"正在拖拽");
  NSString* pointStr=NSStringFromCGPoint(self.scrollview.contentOffset) ;
  NSLog(@"%@",pointStr);
}

//结束拖拽
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
  NSLog(@"结束拖拽");

}

- (void)viewDidLoad {
  [super viewDidLoad];
  //设置scrollView的宽高
  self.scrollview.contentSize=self.imgView.image.size;
  //通常使用控制器作为代理对象,实际就是self
  //1、为UIScrollView找一个代理对象,也就是设置UIScrollView的delegate属性
  self.scrollview.delegate=self;

}


@end

输出:
2020-06-28 16:21:21.069764+0800 IOS040[5909:220727] {221.5, 312.5}
2020-06-28 16:21:21.085941+0800 IOS040[5909:220727] 正在拖拽
2020-06-28 16:21:21.086179+0800 IOS040[5909:220727] {224.5, 316.5}
2020-06-28 16:21:21.102507+0800 IOS040[5909:220727] 正在拖拽
2020-06-28 16:21:21.102678+0800 IOS040[5909:220727] {227, 320}
2020-06-28 16:21:21.105778+0800 IOS040[5909:220727] 即将开始拖拽
2020-06-28 16:21:21.369434+0800 IOS040[5909:220727] 结束拖拽

6.通过代理注册事件实现内容缩放

思路
1、拖拽一个UIScrollView
2、向UIScrollView中添加内容(这里的内容就是指要缩放的内容(控件))
3、通过代理监听缩放时间,在缩放实践中返回UIScrollView的某个子控件(这个子控件就是告诉UIScrollView对这个控件进行缩放)
4、设置缩放比:最大能放大多少倍,最小能缩小百分之多少
5、一次只能缩放一个子控件

#import "ViewController.h"
//设置代理协议
@interface ViewController ()<UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIImageView *imgView;

@end

@implementation ViewController
//实现缩放方法,在这个方法中返回要进行缩放的子控件
-(UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView{
  NSLog(@"实现缩放scrollViewWillBeginZooming");
  //返回图片框进行缩放
  return self.imgView;
}
//即将开始缩放
-(void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view{
  NSLog(@"即将开始缩放scrollViewWillBeginZooming");
}
//正在缩放

 - -(void)scrollViewDidZoom:(UIScrollView *)scrollView{

  NSLog(@"正在缩放scrollViewDidZoom");
}
//结束缩放
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale{
  NSLog(@"结束缩放scrollViewDidEndZooming");
}

- (void)viewDidLoad {
  [super viewDidLoad];
  //设置scrollView的缩放比例
  self.scrollView.maximumZoomScale=3.5;
  self.scrollView.minimumZoomScale=0.5;
}


@end

在这里插入图片描述

7.图片浏览器–分页
#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  //动态创建imageview并放入到scrollView
  CGFloat img_W=300;
  CGFloat img_H=130;
  CGFloat img_Y=0;
  
  for (int i=0; i<5; i++) {
    //创建一个UIView
    UIImageView* imageview=[[UIImageView alloc]init];
    //设置这个uiview的大小图片
    imageview.image=[UIImage imageNamed:[NSString stringWithFormat:@"img_%02d",i+1]];
    CGFloat img_X=i*img_W;
    imageview.frame=CGRectMake(img_X, img_Y, img_W, img_H);
    //将图片添加到scrollView
    [self.scrollView addSubview:imageview];
  }
  //设置scrollview的滚动
  CGFloat maxW=self.scrollView.frame.size.width*5;
  self.scrollView.contentSize=CGSizeMake(maxW, img_H);
  
  //实现UIScrollView的分页效果
  self.scrollView.pagingEnabled=YES;
  
  //隐藏滚动指示器
  self.scrollView.showsHorizontalScrollIndicator=NO;
  
}
@end

在这里插入图片描述

8.图片浏览器–分页指示器

设置分页的思路:
1、更具UIScrollView滚动到第几张图片,设置pageController当前第几个点显示为current page
2、当前页的数值=(当前滚动的偏移contentOffset.x+半个图片的宽度)/每个图片的宽度
为什么要偏移加半个宽度?
如果contentOffset.x小于半个宽度,那么加上半个宽度以后除以图片宽度,结果还是0;
如果contentOffset.x大于半个宽度,那么加上半个宽度以后除以一个宽度,结果还是1

#import "ViewController.h"

@interface ViewController ()<UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  //动态创建imageview并放入到scrollView
  CGFloat img_W=300;
  CGFloat img_H=130;
  CGFloat img_Y=0;
  
  for (int i=0; i<5; i++) {
    //创建一个UIView
    UIImageView* imageview=[[UIImageView alloc]init];
    //设置这个uiview的大小图片
    imageview.image=[UIImage imageNamed:[NSString stringWithFormat:@"img_%02d",i+1]];
    CGFloat img_X=i*img_W;
    imageview.frame=CGRectMake(img_X, img_Y, img_W, img_H);
    //将图片添加到scrollView
    [self.scrollView addSubview:imageview];
  }
  //设置scrollview的滚动
  CGFloat maxW=self.scrollView.frame.size.width*5;
  self.scrollView.contentSize=CGSizeMake(maxW, img_H);
  
  //实现UIScrollView的分页效果
  self.scrollView.pagingEnabled=YES;
  
  //隐藏滚动指示器
  self.scrollView.showsHorizontalScrollIndicator=NO;
  
  //将分页控制器子控件防到最前
  //[self.scrollView bringSubviewToFront:self.pageControl];
  //x:112 y:93 w:39 H:39
  self.pageControl.numberOfPages=5;
  self.pageControl.currentPage=0;
  
}
//实现滚动方法
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
  //实现滚动方法
  //1、获取动动的x方向的偏移值
  CGFloat offsetX=scrollView.contentOffset.x;
  offsetX+=scrollView.frame.size.width*0.5;
  //2、用x方向的偏移值/一张图片的宽度,取商就得到了当前滚动到了第一页(索引)
  int currentpage=offsetX/self.scrollView.frame.size.width;
  //3、将页码设置给pageController
  self.pageControl.currentPage=currentpage;
}


@end

在这里插入图片描述

9.图片浏览器–自动滚动(NStimer)

两种不同的定时器

  • NSTimer(间隔时间比较大,1秒,几秒等)
  • CAdisplayLink(间隔时间比较小,0.0几秒)
    通过NSTimer启动定时器的两种方法
  • 调用timerWithXxx创建的timer,需要把这个tiemr对象手动加到消息循环中,再调用一次fire才能启动
  • 调用schedulTimerWithXxx创建的timer,不需要再调用一次fire自动启动
#import "ViewController.h"

@interface ViewController ()<UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  //动态创建imageview并放入到scrollView
  CGFloat img_W=300;
  CGFloat img_H=130;
  CGFloat img_Y=0;
  
  for (int i=0; i<5; i++) {
    //创建一个UIView
    UIImageView* imageview=[[UIImageView alloc]init];
    //设置这个uiview的大小图片
    imageview.image=[UIImage imageNamed:[NSString stringWithFormat:@"img_%02d",i+1]];
    CGFloat img_X=i*img_W;
    imageview.frame=CGRectMake(img_X, img_Y, img_W, img_H);
    //将图片添加到scrollView
    [self.scrollView addSubview:imageview];
  }
  //设置scrollview的滚动
  CGFloat maxW=self.scrollView.frame.size.width*5;
  self.scrollView.contentSize=CGSizeMake(maxW, img_H);
  
  //实现UIScrollView的分页效果
  self.scrollView.pagingEnabled=YES;
  
  //隐藏滚动指示器
  self.scrollView.showsHorizontalScrollIndicator=NO;
  
  //将分页控制器子控件防到最前
  //[self.scrollView bringSubviewToFront:self.pageControl];
  self.pageControl.numberOfPages=5;
  self.pageControl.currentPage=0;
  
  //创建一个定时器控件,这个定时器会自动启动因为是scheduled
  NSTimer* timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(scrollImage) userInfo:nil repeats:YES];
  
}

-(void)scrollImage{
  //滚动一次图片,实际设置contentOffset的值
  //1、拿到当前的页数
  NSInteger pageNumber=self.pageControl.currentPage;
  //2、判断是否到了最后一页,如果到了,则设页数为0,如果没到页数++,并让scrollView的contentOffset做出对应的偏转
  if (pageNumber==self.pageControl.numberOfPages-1) {
    //表示已经到达最后一页,设page=0
    pageNumber=0;
  }else{
    pageNumber++;
  }
  CGFloat offsetX=pageNumber*self.scrollView.frame.size.width;
  [self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
  
  //3、如果已经滚动到最后一页,则滚动到下一页
  
}
//实现滚动方法
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
  //实现滚动方法
  //1、获取动动的x方向的偏移值
  CGFloat offsetX=scrollView.contentOffset.x;
  offsetX+=scrollView.frame.size.width*0.5;
  //2、用x方向的偏移值/一张图片的宽度,取商就得到了当前滚动到了第一页(索引)
  int currentpage=offsetX/self.scrollView.frame.size.width;
  //3、将页码设置给pageController
  self.pageControl.currentPage=currentpage;
}
@end
10.图片浏览器–bug修复–调整线程优先级
#import "ViewController.h"

@interface ViewController ()<UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
//创建一个用来引用的计时器对象的属性
@property (strong,nonatomic) NSTimer* timer;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  //动态创建imageview并放入到scrollView
  CGFloat img_W=300;
  CGFloat img_H=130;
  CGFloat img_Y=0;
  
  for (int i=0; i<5; i++) {
    //创建一个UIView
    UIImageView* imageview=[[UIImageView alloc]init];
    //设置这个uiview的大小图片
    imageview.image=[UIImage imageNamed:[NSString stringWithFormat:@"img_%02d",i+1]];
    CGFloat img_X=i*img_W;
    imageview.frame=CGRectMake(img_X, img_Y, img_W, img_H);
    //将图片添加到scrollView
    [self.scrollView addSubview:imageview];
  }
  //设置scrollview的滚动
  CGFloat maxW=self.scrollView.frame.size.width*5;
  self.scrollView.contentSize=CGSizeMake(maxW, img_H);
  
  //实现UIScrollView的分页效果
  self.scrollView.pagingEnabled=YES;
  
  //隐藏滚动指示器
  self.scrollView.showsHorizontalScrollIndicator=NO;
  
  //将分页控制器子控件防到最前
  //[self.scrollView bringSubviewToFront:self.pageControl];
  self.pageControl.numberOfPages=5;
  self.pageControl.currentPage=0;
  
  //创建一个定时器控件,这个定时器会自动启动因为是scheduled
  self.timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(scrollImage) userInfo:nil repeats:YES];
  
  //修改self.timer的优先级与控件一样
  //创建一个消息循环对象
  NSRunLoop* runloop=[NSRunLoop currentRunLoop];
  //改变self.timer对象的优先级
  [runloop addTimer:self.timer forMode:NSRunLoopCommonModes];
  
}

-(void)scrollImage{
  //滚动一次图片,实际设置contentOffset的值
  //1、拿到当前的页数
  NSInteger pageNumber=self.pageControl.currentPage;
  //2、判断是否到了最后一页,如果到了,则设页数为0,如果没到页数++,并让scrollView的contentOffset做出对应的偏转
  if (pageNumber==self.pageControl.numberOfPages-1) {
    //表示已经到达最后一页,设page=0
    pageNumber=0;
  }else{
    pageNumber++;
  }
  CGFloat offsetX=pageNumber*self.scrollView.frame.size.width;
  [self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
  
  
}
//实现滚动方法
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
  //实现滚动方法
  //1、获取动动的x方向的偏移值
  CGFloat offsetX=scrollView.contentOffset.x;
  offsetX+=scrollView.frame.size.width*0.5;
  //2、用x方向的偏移值/一张图片的宽度,取商就得到了当前滚动到了第一页(索引)
  int currentpage=offsetX/self.scrollView.frame.size.width;
  //3、将页码设置给pageController
  self.pageControl.currentPage=currentpage;
}
//实现即将开始拖拽的方法
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
  //停止定制器
  //使用invalidate一旦停止计时器,那么这个计时器就不能在重用了,下次必须重新创建一个计时器
  [self.timer invalidate];
  //调用完invalidate方法后,这个计时器不能再使用了
  self.timer=nil;
}

//实现拖拽完毕的方法
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
  //重启定制器
  self.timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(scrollImage) userInfo:nil repeats:YES];
  //创建一个消息循环对象
  NSRunLoop* runloop=[NSRunLoop currentRunLoop];
  //改变self.timer对象的优先级
  [runloop addTimer:self.timer forMode:NSRunLoopCommonModes];
}
@end
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐