美文网首页
iOS开发之UI篇(9)—— UIScrollView、UIPa

iOS开发之UI篇(9)—— UIScrollView、UIPa

作者: 看影成痴 | 来源:发表于2017-12-19 11:25 被阅读23次

    版本
    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(0, 20, SCROLL_WIDTH, SCROLL_HEIGHT);
            // 设置滚动区域
            _scrollView.contentSize = CGSizeMake(SCROLL_WIDTH*3, 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=0; i<3; i++) {
            UIImageView *imageView = [[UIImageView alloc] init];
            imageView.frame = CGRectMake(SCROLL_WIDTH*i, 0, 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。

    scrollView内容

    完整代码如下:

    #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=0; i<5; i++) {
            UIImageView *imageView = [[UIImageView alloc] init];
            imageView.frame = CGRectMake(SCROLL_WIDTH*i, 0, SCROLL_WIDTH, SCROLL_HEIGHT);
            imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i]];
            if (i == 0) {
                // 第一个视图显示最后一张图片
                imageView.image = [UIImage imageNamed:@"2.jpg"];
            }else if(i == 4){
                // 第五个视图显示第一张图片
                imageView.image = [UIImage imageNamed:@"0.jpg"];
            }else {
                imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i-1]];
            }
            // 添加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*4) {
            // 移动到第一个视图
            scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*1, 0);
        }else if(scrollView.contentOffset.x <= 0){
            // 移到第三个视图
            scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*3, 0);
        }
    }
    
    
    #pragma mark - 懒加载
    
    - (UIScrollView *)scrollView {
        
        if (_scrollView == nil) {
            // 实例化
            _scrollView = [[UIScrollView alloc] init];
            // 设置尺寸大小
            _scrollView.frame = CGRectMake(0, 20, SCROLL_WIDTH, SCROLL_HEIGHT);
            // 设置滚动区域
            _scrollView.contentSize = CGSizeMake(SCROLL_WIDTH*5, SCROLL_HEIGHT);
            // 隐藏水平滑条
            _scrollView.showsHorizontalScrollIndicator = NO;
            // 设置分页(每次滑动一页)
            _scrollView.pagingEnabled = YES;
            // 弹簧效果(边界拉出来一小段会弹回去)
            _scrollView.bounces = NO;    //关闭
            _scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*1, 0);
            // 设置代理方法
            _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=0; i<5; i++) {
            UIImageView *imageView = [[UIImageView alloc] init];
            imageView.frame = CGRectMake(SCROLL_WIDTH*i, 0, SCROLL_WIDTH, SCROLL_HEIGHT);
            imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i]];
            if (i == 0) {
                // 第一个视图显示最后一张图片
                imageView.image = [UIImage imageNamed:@"2.jpg"];
            }else if(i == 4){
                // 第五个视图显示第一张图片
                imageView.image = [UIImage imageNamed:@"0.jpg"];
            }else {
                imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i-1]];
            }
            // 添加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:3.0 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:3.0 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 >= 5) {
            tempPoint.x = 0;
        }
        self.scrollView.contentOffset = tempPoint;
        [self updateContentOffsetAndCurrentPage];
    }
    
    
    // 更新当前图片和页数
    - (void)updateContentOffsetAndCurrentPage {
        
        // 更新偏移量
        if (self.scrollView.contentOffset.x >= SCROLL_WIDTH*4) {
            // 移动到第一个视图
            self.scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*1, 0);
        }else if(self.scrollView.contentOffset.x <= 0){
            // 移到第三个视图
            self.scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*3, 0);
        }
        
        // 更新当前页数
        NSInteger currentPage = (self.scrollView.contentOffset.x-SCROLL_WIDTH)/SCROLL_WIDTH;
        if (currentPage < 0) {
            currentPage = 0;
        }else if (currentPage > 2) {
            currentPage = 2;
        }
        self.pageControl.currentPage = currentPage;
    }
    
    
    #pragma mark - 懒加载
    
    - (UIScrollView *)scrollView {
        
        if (_scrollView == nil) {
            // 实例化
            _scrollView = [[UIScrollView alloc] init];
            // 设置尺寸大小
            _scrollView.frame = CGRectMake(0, 20, SCROLL_WIDTH, SCROLL_HEIGHT);
            // 设置滚动区域
            _scrollView.contentSize = CGSizeMake(SCROLL_WIDTH*5, SCROLL_HEIGHT);
            // 隐藏水平滑条
            _scrollView.showsHorizontalScrollIndicator = NO;
            // 设置分页(每次滑动一页)
            _scrollView.pagingEnabled = YES;
            // 弹簧效果(边界拉出来一小段会弹回去)
            _scrollView.bounces = NO;    //关闭
            _scrollView.contentOffset = CGPointMake(SCROLL_WIDTH*1, 0);
            // 设置代理方法
            _scrollView.delegate = self;
        }
        
        return _scrollView;
    }
    
    
    - (UIPageControl *)pageControl {
        
        if (_pageControl == nil) {
            // 实例化UIPageControl
            _pageControl = [[UIPageControl alloc] init];
            _pageControl.frame = CGRectMake(0, 20+SCROLL_HEIGHT-30, SCROLL_WIDTH, 30);
            // 设置总页数
            _pageControl.numberOfPages = 3;
            // 设置背景色
            _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*5, SCROLL_HEIGHT*5);
            _scrollView.minimumZoomScale = 0.5;     // 最小缩小比例
            _scrollView.maximumZoomScale = 2.0;     // 最大放大比例
    

    然后在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(3_2) {
        
        NSLog(@"%s",__func__);
    }
    
    
    // 正在缩放 (手动拖拽及代码设置均会调用,可能多次调用)
    - (void)scrollViewDidZoom:(UIScrollView *)scrollView NS_AVAILABLE_IOS(3_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(5_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(3_2);
    
    // 正在缩放 (手动拖拽及代码设置均会调用,可能多次调用)
    - (void)scrollViewDidZoom:(UIScrollView *)scrollView NS_AVAILABLE_IOS(3_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(11.0), tvos(11.0));
    

    二、使用XIB与storyboard创建

    和UIView的创建差不多,就多了个delegate的关联,就不浪费时间贴上了。可参阅之前的博文:http://www.jianshu.com/p/9362d0274ed5

    相关文章

      网友评论

          本文标题:iOS开发之UI篇(9)—— UIScrollView、UIPa

          本文链接:https://www.haomeiwen.com/subject/kgkbwxtx.html