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

本文介绍了一个无限轮播功能图的iOS组件封装过程,包括所需文件、实现原理及使用方法。该组件支持本地和远程图片加载,并实现了自动轮播及触摸控制等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 无限轮播功能图

这里写图片描述

二 封装的.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 明天为大家带来新的内容,希望大家能满意.如果大家觉得我写的博客还行,那么请关注我的官方博客,谢谢!!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值