iOS基础--轮播图

上一篇已经介绍了UIScrollView的使用,并且简单的写了一个轮播图的例子,但是上一篇中的轮播图不能自动滚动,也不能循环轮播。今天有时间整理一下自动循环轮播的真正轮播图实例。

循环轮播图的原理

实现循环轮播的原理现在常用的有两种:
1、创建n+2个滚动子视图。在滚动到首尾时候进行转换调整。
2、创建3个滚动子视图,每次滚动结束进行图片位置调整。
本实例代码使用第二种方式,创建3个滚动子视图。
废话不多说,直接上代码,在代码中做了详细的注释。

自定义类CustomerView.h文件代码

#import <UIKit/UIKit.h>

//声明协议,给轮播图的点击添加一个代理
//这里使用@class是因为下面的代理方法需要使用到本类。
@class CustomerView;
@protocol CustomerViewDelegate<NSObject>
@optional
//代理方法 点击图片回调
- (void)customerView:(CustomerView *)view indexOfClickedImage:(NSInteger)index;
@end

@interface CustomerView : UIView

//传入用于轮播图的图片数组
@property (nonatomic, copy)NSArray *images;

//pageControl颜色设置
@property (nonatomic, strong) UIColor *currentPageColor;
@property (nonatomic, strong) UIColor *pageColor;

//代理
@property (nonatomic, weak) id<CustomerViewDelegate> delegate;

@end

自定义类CustomerView.m文件代码

#import "CustomerView.h"

//轮播图创建的图片数量
static const int imageCount = 3;

//准守UIScrollViewDelegate协议
@interface CustomerView ()<UIScrollViewDelegate>

//定义全局变量在后面的自动轮播方法中使用
@property (nonatomic, weak)UIScrollView *scrollView;
@property (nonatomic, weak)UIPageControl *pageControl;
//定时器,用于自动轮播
@property (nonatomic, weak)NSTimer *timer;

@end

@implementation CustomerView

- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        //定义一个scrollView,最主要的轮播控件
        UIScrollView *scrollView = [[UIScrollView alloc] init];
        scrollView.delegate = self;
        //横竖两种滚轮都不显示
        scrollView.showsVerticalScrollIndicator = NO;
        scrollView.showsHorizontalScrollIndicator = NO;
        //需要分页
        scrollView.pagingEnabled = YES;
        //不需要回弹
        scrollView.bounces = NO;
        [self addSubview:scrollView];
        self.scrollView = scrollView;
        
        //在scrollView中添加三个图片
        for (int i = 0;i < imageCount; i++) {
            UIImageView *imageView = [[UIImageView alloc] init];
            [scrollView addSubview:imageView];
        }
        //添加pageControl
        UIPageControl *pageControl = [[UIPageControl alloc] init];
        [self addSubview:pageControl];
        self.pageControl = pageControl;
    }
    
    return self;
}

//布局子控件
- (void)layoutSubviews {
    [super layoutSubviews];
    //设置scrollView的frame
    self.scrollView.frame = self.bounds;
    
    CGFloat width = self.bounds.size.width;
    CGFloat height = self.bounds.size.height;
    //设置contentSize,不同轮播方向的时候contentSize是不一样的
    //contentSize要放三张图片
    self.scrollView.contentSize = CGSizeMake(width * imageCount, height);
    //设置三张图片的位置,并为三个图片添加点击事件
    for (int i = 0; i < imageCount; i++) {
        UIImageView *imageView = self.scrollView.subviews[i];
        //给图片添加点击手势
        imageView.userInteractionEnabled = YES;
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewClick:)];
        [imageView addGestureRecognizer:tap];
        //设置图片大小,和View相同
        imageView.frame = CGRectMake(i * width, 0, width, height);
    }
    //设置contentOffset,显示最中间的图片
    self.scrollView.contentOffset = CGPointMake(width, 0);
    
    //设置pageControl的位置
    CGFloat pageW = 100;
    CGFloat pageH = 20;
    CGFloat pageX = width/2-50;
    CGFloat pageY = height - pageH;
    self.pageControl.frame = CGRectMake(pageX, pageY, pageW, pageH);
}

//设置pageControl的CurrentPageColor
- (void)setCurrentPageColor:(UIColor *)currentPageColor {
    _currentPageColor = currentPageColor;
    self.pageControl.currentPageIndicatorTintColor = currentPageColor;
}

//设置pageControl的pageColor
- (void)setPageColor:(UIColor *)pageColor {
    _pageColor = pageColor;
    self.pageControl.pageIndicatorTintColor = pageColor;
}

//根据传入的图片数组设置图片
- (void)setImages:(NSArray *)images {
    _images = images;
    //pageControl的页数就是图片的个数
    self.pageControl.numberOfPages = images.count;
    //默认一开始显示的是第0页
    self.pageControl.currentPage = 0;
    //设置图片显示内容
    [self setContent];
    //开启定时器
    [self startTimer];
    
}

//设置显示内容
- (void)setContent {
    //设置三个imageBtn的显示图片
    for (int i = 0; i < self.scrollView.subviews.count; i++) {
        //取出三个imageView
        UIImageView *imageView = self.scrollView.subviews[i];
        //这个是为了给图片做索引用的
        NSInteger index = self.pageControl.currentPage;
        
        if (i == 0) { //第一个imageView,隐藏在当前显示的imageView的左侧
            index--; //当前页索引减1就是第一个imageView的图片索引
        } else if (i == 2) { //第三个imageView,隐藏在当前显示的imageView的右侧
            index++; //当前页索引加1就是第三个imageView的图片索引
        }
        //无限循环效果的处理就在这里
        if (index < 0) { //当上面index为0的时候,再向右拖动,左侧图片显示,这时候我们让他显示最后一张图片
            index = self.pageControl.numberOfPages - 1;
        } else if (index == self.pageControl.numberOfPages) { //当上面的index超过最大page索引的时候,也就是滑到最右再继续滑的时候,让他显示第一张图片
            index = 0;
        }
        imageView.tag = index;
        //用上面处理好的索引给imageView设置图片
        imageView.image = self.images[index];
        
    }
}

//状态改变之后更新显示内容
- (void)updateContent {
    CGFloat width = self.bounds.size.width;
    [self setContent];
    //唯一跟设置显示内容不同的就是重新设置偏移量,让它永远用中间的按钮显示图片,滑动之后就偷偷的把偏移位置设置回去,这样就实现了永远用中间的按钮显示图片
    //设置偏移量在中间
    self.scrollView.contentOffset = CGPointMake(width, 0);
}

#pragma mark - UIScrollViewDelegate
//拖拽的时候执行哪些操作
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    //拖动的时候,哪张图片最靠中间,也就是偏移量最小,就滑到哪页
    //用来设置当前页
    NSInteger page = 0;
    //用来拿最小偏移量
    CGFloat minDistance = MAXFLOAT;
    //遍历三个imageView,看那个图片偏移最小,也就是最靠中间
    for (int i = 0; i < self.scrollView.subviews.count; i++) {
        UIImageView *imageView = self.scrollView.subviews[i];
        CGFloat distance = 0;
        distance = ABS(imageView.frame.origin.x - scrollView.contentOffset.x);
        if (distance < minDistance) {
            minDistance = distance;
            page = imageView.tag;
        }
    }
    self.pageControl.currentPage = page;
}

//开始拖拽的时候停止计时器
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    [self stopTimer];
}

//结束拖拽的时候开始定时器
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    [self startTimer];
}

//结束拖拽的时候更新image内容
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self updateContent];
}

//scroll滚动动画结束的时候更新image内容
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    [self updateContent];
}

#pragma mark - 定时器
//开始计时器
- (void)startTimer {
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    self.timer = timer;
}

//停止计时器
- (void)stopTimer {
    //结束计时
    [self.timer invalidate];
    //计时器被系统强引用,必须手动释放
    self.timer = nil;
}

//通过改变contentOffset * 2换到下一张图片
- (void)nextImage {
    CGFloat width = self.bounds.size.width;
    [self.scrollView setContentOffset:CGPointMake(2 * width, 0) animated:YES];
}

- (void)imageViewClick:(UITapGestureRecognizer *)tap {
    //    NSLog(@"%ld",btn.tag);
    UIView *imageView = tap.view;
    if ([self.delegate respondsToSelector:@selector(customerView:indexOfClickedImage:)])
    {
        [self.delegate customerView:self indexOfClickedImage:imageView.tag];
    }
    
}

@end

ViewController中调用代码

#import "ViewController.h"
#import "CustomerView.h"

//遵守协议
@interface ViewController ()<CustomerViewDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //创建视图
    CustomerView *customerView = [[CustomerView alloc] initWithFrame:CGRectMake(0, 20, [UIScreen mainScreen].bounds.size.width, 300)];
    //设置代理
    customerView.delegate = self;
    //图片数组赋值
    customerView.images = @[
                        [UIImage imageNamed:@"image_0.jpg"],
                        [UIImage imageNamed:@"image_1.jpg"],
                        [UIImage imageNamed:@"image_2.jpg"],
                        [UIImage imageNamed:@"image_3.jpg"]
                        ];
    
    customerView.currentPageColor = [UIColor whiteColor];
    customerView.pageColor = [UIColor blueColor];
    [self.view addSubview:customerView];
}

#pragma mark--CustomerViewDelegate  实现代理方法
- (void)customerView:(CustomerView *)view indexOfClickedImage:(NSInteger)index{
    NSLog(@"点击了第%ld张图片",index);
}

@end

全部代码都已经贴出来了,就不再上传demo了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章