UIScrollView 的缩放原理

1,475 阅读5分钟

「这是我参与2022首次更文挑战的第38天,活动详情查看:2022首次更文挑战」。

引言

iOS ScrollView的使用教程:kunnan.blog.csdn.net/article/det…

iOS 利用UIScrollView实现图片放大预览,并支持缩小:blog.csdn.net/z929118967/…

I UIScrollView 的缩放原理

当用户在UIScrollView身上使用捏合手势时,UIScrollView会给delegate对象发送一条消息,询问delegate究竟要缩放自己内部的哪个子控件(那一块内容)


- (void) scrollViewWillBeginZooming:(UIScrollView *)scrollView  withView:(UIView *)view;//准备开始缩放的时候调用
- (void)scrollViewDidZoom:(UIScrollView *)scrollView;//正在缩放的时候调用

当用户使用捏合手势的时候,UIScrollView 会调用delegate对象的viewForZoomingInScrollView:方法,这个方法返回的控件就是需要进行缩放的控件。

缩放实现步骤:

  1. 设置UIScrollView的iddelegate对象
  2. 设置minimumZoomScale、MaximumZoomScale 缩小、放大的最大比例
  3. delegate对象实现viewForZoomingInScrollView:方法,返回需要缩放的视图控件

II 分页的实现

只要将UIScrollView 的属性PageEnabled设为YES,UIScrollView会被分割成多个独立的页面,里面的内容就能进行分页展示 通常配合UIPageControl使用,来增强分页效果

UIPageControl 的常见属性:

//一共有多少页
@property(nonatomic) NSInteger numberOfPages;
//当前显示的页码
@property(nonatomic) NSInteger currentPage;
//只有一页时,是否需要隐藏页码指示器
@property(nonatomic) BOOL hidesForSinglePage;
//其他页码指示器的颜色
@property(nonatomic,retain) UIColor *pageIndicatorTintColor;
//当前页码指示器的颜色
@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor; 

III 基础知识

3.1 getter/setter的重写细节

getter、setter的重写细节

/**
 图像的setter方法;setter方法,除了赋值,还执行了contentSize的设置动作
 */
- (void)setImage:(UIImage *)image{
    //setter方法的第一个步骤:给属性进行赋值
    _image = image;
    //设置图像视图的内容
    [self.imageView setImage:_image];
    //让图像视图,根据图像大小,自动调整自己的视图大小
    [self.imageView sizeToFit];//Resizes and moves the receiver view so it just encloses its subviews.
    //告诉图像视图,内部内容实际的大小
    [self.scrollView setContentSize:_image.size];
}
/**
 0.getter 方法的重写
 * 使用自身对象的时候,使用_属性名称进行获取
 *使用其他成员属性的时候,使用self.gtter 方法,这样可以及时的实例化对用的成员属性
 1.懒加载imageView属性,重写getter方法--使用对象dot属性名称的时候,会调用getter方法,_属性名称不会调用getter方法
 */
- (UIImageView *)imageView{
    if (nil == _imageView) {
        //创建imageView
        UIImageView *tmpImageView = [[UIImageView alloc]init];
        _imageView=tmpImageView;
        [self.scrollView addSubview:_imageView];
    }
    return _imageView;
}

3.2 NSTimer 定时器

kunnan.blog.csdn.net/article/det…

3.3 图片轮播器

开发步骤:

  1. scrollView getter方法懒加载 只指定了大小,添加到视图
  2. viewDidLoad中添加图像,并且计算位置
  3. 运行观察效果,修改scrollView的属性.......
  4. 实例化UIPageControl
  5. 因为分页控件和滚动视图是分离的,因此监听滚动停止代理方法,修改分页控件的页数
  6. 将UIPageControl定义成属性,并且添加监听方法
  7. 实现监听方法,页数变化后,修改scrollView的位置
  8. 添加时钟,调用分页控件的监听方法,实现图片自动轮播
/  ViewController.m
/**
 今天的开发步骤:
 1. scrollView getter方法懒加载
 
 只指定了大小,添加到视图
 
  
 
 2. viewDidLoad中添加图像,并且计算位置
 
  
 
 3. 运行观察效果,修改scrollView的属性.......
 
  
 
 4. 实例化UIPageControl
 
  
 
 5. 因为分页控件和滚动视图是分离的,因此监听滚动停止代理方法,修改分页控件的页数
 
  
 
 6. 将UIPageControl定义成属性,并且添加监听方法
 
  
 
 7. 实现监听方法,页数变化后,修改scrollView的位置
 
  
 
 8. 添加时钟,调用分页控件的监听方法,实现图片自动轮播
 
 */
 
//
 
//  Created by devzkn on 3/18/16.
 
//  Copyright © 2016 hisun. All rights reserved.
 
//
 
 
 
 
#import "ViewController.h"
 
#define kImageCount 5
 
 
 
 
@interface ViewController () <UIScrollViewDelegate>
 
@property (nonatomic,weak) UIScrollView *scrollView;
 
@property (nonatomic,weak) UIPageControl *pageControl;
 
@property (nonatomic,strong) NSTimer *timer;
 
 
 
 
@end
 
 
 
 
@implementation ViewController
 
 
 
 
/**
 
 重写getter方法,进行懒加载实例化属性对象
 
 */
 
- (UIPageControl *)pageControl{
 
    if (nil == _pageControl) {
 
        //实例化属性
 
        UIPageControl *tmpPageControl = [[UIPageControl alloc]init];
 
        //设置控件大小
 
        CGSize size = [tmpPageControl sizeForNumberOfPages:kImageCount];
 
        [tmpPageControl setBounds:CGRectMake(0, 0, size.width, size.height)];
 
        //设置总页数
 
        [tmpPageControl setNumberOfPages:kImageCount];
 
        //设置颜色
 
        [tmpPageControl setPageIndicatorTintColor:[UIColor redColor]];
 
        [tmpPageControl setCurrentPageIndicatorTintColor:[UIColor blackColor]];
 
        //设置位置
 
        [tmpPageControl setCenter:CGPointMake(self.view.center.x, CGRectGetHeight(self.scrollView.bounds))];
 
        _pageControl = tmpPageControl;
 
        //添加监听方法:再oc中,继承于UIControl的控件,绝大多数都可以监听UIControlEventValueChanged事件,UIButton除外
 
        [_pageControl addTarget:self action:@selector(changePage) forControlEvents:UIControlEventValueChanged];
 
        [self.view addSubview:_pageControl];
 
    }
 
    return _pageControl;
 
}
 
/**
 
 重写getter方法,进行懒加载方式实例化属性
 
 */
 
- (UIScrollView *)scrollView{
 
    if (nil == _scrollView) {
 
        UIScrollView *tmpScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(10, 20, 300, 130)];
 
        _scrollView = tmpScrollView;
 
        //代理设置、contentSize、contentOffset、contentInset
 
        [_scrollView setDelegate:self];
 
        [_scrollView setContentSize:CGSizeMake(CGRectGetWidth(_scrollView.bounds)*kImageCount, 0)];
 
        //设置分页
 
        [_scrollView setPagingEnabled:YES];
 
        //取消水平滚动条
 
        [_scrollView setShowsHorizontalScrollIndicator:NO];
 
        [_scrollView setShowsVerticalScrollIndicator:NO];
 
        //取消弹簧效果
 
        [_scrollView setBounces:NO];
 
        [_scrollView setBackgroundColor:[UIColor lightGrayColor]];
 
        [self.view addSubview:_scrollView];
 
         
 
    }
 
    return _scrollView;
 
}
 
/**
 
 通常用来设置数据
 
 */
 
- (void)viewDidLoad {
 
    [super viewDidLoad];
 
    //设置图片(内容)
 
    for (int i=0; i<kImageCount; i++) {
 
         NSString *imageName = [NSString stringWithFormat:@"img_%02d",i+1];
 
        UIImage *image = [UIImage imageNamed:imageName] ;
 
        UIImageView *imageView = [[UIImageView alloc]initWithFrame:self.scrollView.bounds];
 
        [imageView setImage:image];
 
        [self.scrollView addSubview:imageView];
 
    }
 
    //计算imageView的位置
 
    [[self.scrollView subviews] enumerateObjectsUsingBlock:^(UIImageView *imageView, NSUInteger idx, BOOL *stop) {
 
        CGRect frame =imageView.frame;
 
        frame.origin.x = idx*CGRectGetWidth(frame);
 
        [imageView setFrame:frame];
 
    }];
 
    [self.pageControl setCurrentPage:0];
 
    //启动时钟
 
    [self startTimer];
 
     
 
     
 
}
 
 
 
 
- (void) startTimer{
 
    //启动时钟(修改UIPageControl 的currentPage 同时也修改UIScrollView 的contentOffset)
 
    self.timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(photoCarousel:) userInfo:nil repeats:YES];
 
    //注册时钟到runloop
 
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
 
}
 
/**
 
 修改scrollView的contentoffset的同时,对UIPageControl进行页码设置,来实现定时图片轮播
 
 */
 
- (void) photoCarousel:(NSTimer *)timer{
 
    //设置页码
 
    [self.pageControl setCurrentPage:((self.pageControl.currentPage+1)%kImageCount)];
 
    //设置偏移位置
 
//    [self.scrollView setContentOffset:CGPointMake(self.pageControl.currentPage*CGRectGetWidth(self.scrollView.bounds), 0) animated:YES];
 
    [self changePage];
 
}
 
 
 
 
#pragma mark scrollView 的代理方法
 
/**
 
 Tells the delegate that the scroll view has ended decelerating the scrolling movement.
 
 */
 
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
 
    //更新pageControl的页码
 
//    UIPageControl *pageControl =[[self.view subviews]lastObject];
 
    self.pageControl.currentPage= scrollView.contentOffset.x/ CGRectGetWidth(scrollView.bounds);
 
}
 
//抓住图片时,停止时钟
 
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
 
    [self.timer invalidate];
 
    NSLog(@"%s",__FUNCTION__);
 
 
 
 
}
 
// 停止抓住图片时,开启时钟
 
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
 
    [self startTimer];
 
    NSLog(@"%s",__FUNCTION__);
 
}
 
 
 
 
 
 
 
/**
 
 切换图片(修改UIScrollView 显示的UIImageView对象,即修改contentOffSize即可 )
 
 */
 
- (void) changePage{//根据pageControl的页码,来调整UIScrollView的内容(图像)位置
 
    CGFloat x= self.pageControl.currentPage*CGRectGetWidth(self.scrollView.frame);
 
    [self.scrollView setContentOffset:CGPointMake(x, 0) animated:YES];
 
}
 
@end
                                 

see also

🍅 联系作者: iOS逆向(公号:iosrev)


🍅 作者简介:CSDN 博客专家认证🏆丨全站 Top 50、华为云云享专家认证🏆、iOS逆向公号号主


🍅 简历模板、技术互助。关注我,都给你。