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

版本
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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值