基于UICollectionView的无限轮播器(封装)

Posted 萧家大公子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于UICollectionView的无限轮播器(封装)相关的知识,希望对你有一定的参考价值。

一 无限轮播功能图

二 封装的.h文件

//
//  XFJInfiniteScrollView.h
//  无限轮播器
//
//  Created by xiaofeng on 16/4/21.
//  Copyright © 2016年 肖锋. All rights reserved.
//

#import <UIKit/UIKit.h>

@class XFJInfiniteScrollView;

@protocol XFJInfiniteScrollViewDelegate <NSObject>
@optional
- (void)infiniteScrollView:(XFJInfiniteScrollView *)infiniteScrollView didClickImageAtIndex:(NSInteger)index;
@end

@interface XFJInfiniteScrollView : UIView
/** 需要显示的图片数据(要求里面存放UIImage\\NSURL对象) */
@property (nonatomic, strong) NSArray *images;
/** 下载远程图片时的占位图片 */
@property (nonatomic, strong) UIImage *placeholderImage;
/** 用来监听框架内部事件的代理 */
@property (nonatomic, weak) id delegate;
@end

三 封装.m文件

//
//  XFJInfiniteScrollView.m
//  无限轮播器
//
//  Created by xiaofeng on 16/4/21.
//  Copyright © 2016年 肖锋. All rights reserved.
//

#import "XFJInfiniteScrollView.h"
#import "UIImageView+WebCache.h"

#pragma mark - 将有关cell放入同一个类中
@interface XFJImageCell : UICollectionViewCell
@property (weak, nonatomic) UIImageView *imageView;
@end

@implementation XFJImageCell

- (instancetype)initWithFrame:(CGRect)frame

    if (self = [super initWithFrame:frame]) 
        UIImageView *imageView = [[UIImageView alloc] init];
        [self.contentView addSubview:imageView];
        self.imageView = imageView;
    
    return self;


- (void)layoutSubviews

    [super layoutSubviews];

    self.imageView.frame = self.bounds;

@end

#pragma mark - XFJInfiniteScrollView begin
@interface XFJInfiniteScrollView()  <UICollectionViewDataSource, UICollectionViewDelegate>
/** 定时器 */
@property (nonatomic, weak) NSTimer *timer;
/** 用来显示图片的collectionView */
@property (nonatomic, weak) UICollectionView *collectionView;
@end

@implementation XFJInfiniteScrollView

static NSInteger XFJItemCount = 20;
static NSString * const XFJImageCellId = @"XFJImageCell";

- (instancetype)initWithFrame:(CGRect)frame

    if (self = [super initWithFrame:frame]) 
        // 布局
        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        layout.minimumLineSpacing = 0;
        // UICollectionView
        UICollectionView *collectionView =  [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
        collectionView.dataSource = self;
        collectionView.pagingEnabled = YES;
        collectionView.delegate = self;
        collectionView.showsHorizontalScrollIndicator = NO;
        collectionView.showsVerticalScrollIndicator = NO;
        [collectionView registerClass:[XFJImageCell class] forCellWithReuseIdentifier:XFJImageCellId];
        [self addSubview:collectionView];
        self.collectionView = collectionView;
        // 默认属性值
        self.placeholderImage = [UIImage imageNamed:@"XFJInfiniteScrollView.bundle/placeholderImage"];
    
    return self;


- (void)setImages:(NSArray *)images

    _images = images;

    // 设置默认显示最中间的图片
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^
        [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:(XFJItemCount * images.count) / 2 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
    );

    // 开启定时器
    [self startTimer];


- (void)layoutSubviews

    [super layoutSubviews];

    // collectionView
    self.collectionView.frame = self.bounds;

    // layout
    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
    layout.itemSize = self.bounds.size;


#pragma mark - 定时器
- (void)startTimer

    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];


- (void)stopTimer

    [self.timer invalidate];
    self.timer = nil;


- (void)nextPage

    CGPoint offset = self.collectionView.contentOffset;
    offset.x += self.collectionView.frame.size.width;
    [self.collectionView setContentOffset:offset animated:YES];


#pragma mark - <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

    return XFJItemCount * self.images.count;


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

    XFJImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:XFJImageCellId forIndexPath:indexPath];

    id data = self.images[indexPath.item % self.images.count];
    if ([data isKindOfClass:[UIImage class]]) 
        cell.imageView.image = data;
     else if ([data isKindOfClass:[NSURL class]]) 
        [cell.imageView sd_setImageWithURL:data placeholderImage:self.placeholderImage];
    
    return cell;


#pragma mark - 其他
/**
 *  重置cell的位置到中间
 */
- (void)resetPosition

    // 滚动完毕时,自动显示最中间的cell
    NSInteger oldItem = self.collectionView.contentOffset.x / self.collectionView.frame.size.width;
    NSInteger newItem = (XFJItemCount * self.images.count / 2) + (oldItem % self.images.count);
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:newItem inSection:0];
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionNone animated:NO];


#pragma mark - <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

    if ([self.delegate respondsToSelector:@selector(infiniteScrollView:didClickImageAtIndex:)]) 
        [self.delegate infiniteScrollView:self didClickImageAtIndex:indexPath.item % self.images.count];
    


- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

    // 停止定时器
    [self stopTimer];


- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate

    // 开启定时器
    [self startTimer];


/**
 *  scrollView滚动完毕的时候调用(通过setContentOffset:animated:滚动)
 */
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView

    [self resetPosition];


/**
 *  scrollView滚动完毕的时候调用(人为拖拽滚动)
 */
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

    [self resetPosition];

@end

四 用法

1 在外界直接运用

#import "ViewController.h"
#import "XFJInfiniteScrollView.h"

@interface ViewController () <XFJInfiniteScrollViewDelegate>

@end

@implementation ViewController

- (void)viewDidLoad 
    [super viewDidLoad];

    XFJInfiniteScrollView *scrollView = [[XFJInfiniteScrollView alloc] init];
    //需要传入的轮播图片
    scrollView.images = @[
                          [UIImage imageNamed:@"img_00"],
                          [UIImage imageNamed:@"img_01"],
                          [NSURL URLWithString:@"http://tupian.enterdesk.com/2013/mxy/12/10/15/3.jpg"],
                          [UIImage imageNamed:@"img_03"],
                          ];
    scrollView.frame = CGRectMake(0, 0, self.view.frame.size.width, 200);
    scrollView.delegate = self;
    [self.view addSubview:scrollView];


#pragma mark - <XFJInfiniteScrollViewDelegate>
//用来监听点击某个cell,跳转到相应的页面
- (void)infiniteScrollView:(XFJInfiniteScrollView *)infiniteScrollView didClickImageAtIndex:(NSInteger)index

    NSLog(@"点击了第%zd张图片", index);

五 总结

1 今天给大家封装一个无限轮播功能图,只要在公司需要用到此Demo的时候,直接将文件拷贝过去就能用了.另外很多公司有page的显示部分,这样只能根据每个公司的不同而定的,所以这部分我就没有加入进去.

2 明天为大家带来新的内容,希望大家能满意.如果大家觉得我写的博客还行,那么请关注我的官方博客,谢谢!!!!

以上是关于基于UICollectionView的无限轮播器(封装)的主要内容,如果未能解决你的问题,请参考以下文章

react 实现一个无限循环的轮播器 附github地址

UI-图片轮播器

基于RecyclerView实现的动态图片轮播器

jQuery补充,基于jQuery的bxslider轮播器插件

flexslider轮播器插件兼容IE6

UICollectionView实现无限轮播