1. 轮播图有用CollectionView实现的,如SDCycleScrollView github地址:https://github.com/gsdios/SDCycleScrollView
2. 这次用scrollView实现下,假如有1000张图片需要轮播,我们不可能在scrollView上放1000个ImageView吧,那样性能和内存就没法保证了。所以得想办法复用。采用scrollView上放两个ImageView实现轮播图。是一件多么美好的事情啊😄😄。层级结构:
1429074-956225c7acc72a34.png3.位置
-
self.scrollView.contentSize = CGSizeMake(5*KWidth, 0);
KWidth是scrollView的宽度。为什么是5倍的,因为滑的过快会出现问题。之前写的是3倍的出现过卡顿。 -
self.scrollView.contentOffset = CGPointMake(2*KWidth, 0);
让scrollView偏移到中间位置。
-self.currImageView.frame = CGRectMake(2*KWidth, 0, KWidth, KHeight);
将当前显示的currImageView添加到scrollview内容视图的中间位置。所以刚开始显示的是它。因为偏移了2倍的宽度。
scrollView的滑动
当你往右滑动的时候,将otherImageView贴到currImageView的左边。将上一张图片的image放在otherImageView上。所以你看到了上一张图片。当滑动的距离大于等于KWidth,将otherImageView上的图片,贴到currImageView上,快速把scrollView.contentOffset设置为2倍的KWidth。所以你看到是currImageView的图片,但是图片已经被换了,上一张的图片已经变成了当前的图片。很抽象的。如果往左边滑道理是一样的。不再赘述。
关于图片的下载及缓存处理
为了加快下载速度,采用队列的形式,队列里的每个任务是一张图片的下载。下载好的图片存储到沙盒里。图片的名称得来是通过下载的url采用md5加密后的16位码。
上代码
//
// YBCircleScrollView.h
// YBCircleScrollView
//
// Created by wyb on 2017/4/7.
// Copyright © 2017年 xxx. All rights reserved.
//
#import <UIKit/UIKit.h>
@class YBCircleScrollView;
@protocol YBCircleScrollViewDelegate <NSObject>
- (void)circleScrollView:(YBCircleScrollView *)circleScrollView clickImageWithIndex:(NSInteger)index;
@end
@interface YBCircleScrollView : UIView
/**
* 轮播的图片数组,可以是本地图片(UIImage,不能是图片名称),也可以是网络url
*/
@property (nonatomic, strong) NSArray *imageArray;
@property(nonatomic,weak)id<YBCircleScrollViewDelegate> delegate;
/**
清空图片缓存
*/
+ (void)clearCache;
@end
//
// YBCircleScrollView.m
// YBCircleScrollView
//
// Created by wyb on 2017/4/7.
// Copyright © 2017年 中天易观. All rights reserved.
//
#import "YBCircleScrollView.h"
#import <CommonCrypto/CommonDigest.h>
#define KWidth self.bounds.size.width
#define KHeight self.bounds.size.height
@interface YBCircleScrollView ()<UIScrollViewDelegate>
@property(nonatomic,strong)UIScrollView *scrollView;
@property(nonatomic,strong)UIPageControl *pageControl;
//当前显示的imageView
@property (nonatomic, strong) UIImageView *currImageView;
//滚动显示的imageView
@property (nonatomic, strong) UIImageView *otherImageView;
//轮播的图片数组
@property (nonatomic, strong) NSMutableArray *images;
//下载图片的队列
@property (nonatomic, strong) NSOperationQueue *queue;
//定时器
@property(nonatomic,strong)NSTimer *timer;
//当前显示图片的索引
@property (nonatomic, assign) NSInteger currIndex;
//将要显示图片的索引
@property (nonatomic, assign) NSInteger nextIndex;
@end
//缓存图片的文件夹
static NSString *imageCacheDirPath;
@implementation YBCircleScrollView
/**
初始化静态变量时候使用
*/
+ (void)initialize
{
imageCacheDirPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YBimageCacheDir"];
BOOL isDir = NO;
BOOL isExistDir = [[NSFileManager defaultManager] fileExistsAtPath:imageCacheDirPath isDirectory:&isDir];
if (!isDir || !isExistDir) {
//创建文件夹
[[NSFileManager defaultManager] createDirectoryAtPath:imageCacheDirPath withIntermediateDirectories:YES attributes:nil error:nil];
}
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self loadUI];
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self loadUI];
}
return self;
}
- (void)loadUI
{
self.scrollView = [[UIScrollView alloc]init];
self.scrollView.showsVerticalScrollIndicator = NO;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.pagingEnabled = YES;
self.scrollView.bounces = NO;
self.scrollView.delegate = self;
[self addSubview:self.scrollView];
//图片的点击
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(imageClick)];
[self.scrollView addGestureRecognizer:tap];
self.currImageView = [[UIImageView alloc]init];
[self.scrollView addSubview:self.currImageView];
self.otherImageView = [[UIImageView alloc]init];
[self.scrollView addSubview:self.otherImageView];
self.pageControl = [[UIPageControl alloc]init];
self.pageControl.pageIndicatorTintColor = [UIColor grayColor];
self.pageControl.currentPageIndicatorTintColor = [UIColor redColor];
[self addSubview:self.pageControl];
self.queue = [[NSOperationQueue alloc]init];
}
- (void)layoutSubviews
{
[super layoutSubviews];
self.scrollView.frame = self.bounds;
self.pageControl.frame = CGRectMake(0, KHeight - 20, KWidth, 20);
if (self.images.count > 1) {
self.scrollView.contentSize = CGSizeMake(5*KWidth, 0);
self.scrollView.contentOffset = CGPointMake(2*KWidth, 0);
self.currImageView.frame = CGRectMake(2*KWidth, 0, KWidth, KHeight);
[self startTimer];
}else{
self.scrollView.contentSize = CGSizeZero;
self.scrollView.contentOffset = CGPointZero;
self.currImageView.frame = CGRectMake(0, 0, KWidth, KHeight);
[self stopTimer];
}
}
- (void)setImageArray:(NSArray *)imageArray
{
if (imageArray.count == 0) {
return;
}
_imageArray = imageArray;
self.images = [NSMutableArray array];
for (NSInteger i=0; i<imageArray.count; i++) {
id obj = imageArray[i];
if ([obj isKindOfClass:[UIImage class]]) {
[self.images addObject:obj];
}else if ([obj isKindOfClass:[NSString class]]){
//先添加占位图
UIImage *placeHoder = [UIImage imageNamed:@"Placeholder.jpg"];
[self.images addObject:placeHoder];
//下载图片
[self downloadImage:i];
}
}
self.currImageView.image = self.images[self.currIndex];
self.pageControl.numberOfPages = self.images.count;
}
/**
下载图片
@param index 图片索引
*/
- (void)downloadImage:(NSInteger)index
{
NSString *urlString = [self.imageArray objectAtIndex:index];
NSString *imageName = [self MD5ForImageUrl:urlString];
NSString *imagePath = [imageCacheDirPath stringByAppendingPathComponent:imageName];
NSData *data = [NSData dataWithContentsOfFile:imagePath];
//先从沙盒里拿
if (data) {
self.images[index] = [UIImage imageWithData:data];
}else{
//下载图片
NSBlockOperation *downLoadOperation = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
if (data) {
self.images[index] = [UIImage imageWithData:data];
if (self.currIndex == index) {
dispatch_async(dispatch_get_main_queue(), ^{
self.currImageView.image = self.images[index];
});
}
[data writeToFile:imagePath atomically:YES];
}
}];
[self.queue addOperation:downLoadOperation];
}
}
- (void)startTimer
{
if (self.timer) {
[self stopTimer];
}
self.timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(timeAction:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
- (void)stopTimer
{
[self.timer invalidate];
self.timer = nil;
}
- (void)timeAction:(NSTimer *)timer
{
[self.scrollView setContentOffset:CGPointMake(3*KWidth, 0) animated:YES];
}
/**
将图片的urlMD5加密作为图片名称
*/
-(NSString *)MD5ForImageUrl:(NSString *)str{
//要进行UTF8的转码
const char* input = [str UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(input, (CC_LONG)strlen(input), result);
NSMutableString *digest = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[digest appendFormat:@"%02x", result[i]];
}
return digest;
}
#pragma mark 当图片滚动过半时就修改当前页码
- (void)changeCurrendPageWithOffsex:(CGFloat)offset
{
if (offset < KWidth *1.5) {
NSInteger index = self.currIndex - 1;
if (index < 0) {
index = self.images.count - 1;
}
_pageControl.currentPage = index;
}else if (offset > KWidth *2.5)
{
_pageControl.currentPage = (self.currIndex +1) % self.images.count;
}else{
_pageControl.currentPage = self.currIndex;
}
}
#pragma mark-UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat offsetX = scrollView.contentOffset.x;
//更改page
[self changeCurrendPageWithOffsex:offsetX];
//👉滚动
if (offsetX < 2*KWidth) {
self.otherImageView.frame = CGRectMake(KWidth, 0, KWidth, KHeight);
self.nextIndex = self.currIndex - 1;
if (self.nextIndex < 0) {
self.nextIndex = self.images.count - 1;
}
self.otherImageView.image = self.images[self.nextIndex];
if (offsetX <= KWidth) {
[self changeToNextImage];
}
//👈滚动
}else if (offsetX > 2*KWidth)
{
self.otherImageView.frame = CGRectMake(CGRectGetMaxX(self.currImageView.frame), 0, KWidth, KHeight);
self.nextIndex = (self.currIndex + 1) % self.images.count;
self.otherImageView.image = self.images[self.nextIndex];
if (offsetX >= 3*KWidth) {
[self changeToNextImage];
}
}
}
- (void)changeToNextImage
{
//切换到下一张图片
self.currImageView.image = self.otherImageView.image;
self.scrollView.contentOffset = CGPointMake(KWidth * 2, 0);
self.currIndex = self.nextIndex;
self.pageControl.currentPage = self.currIndex;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self stopTimer];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
[self startTimer];
}
+ (void)clearCache
{
NSArray *imageFileNameArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:imageCacheDirPath error:nil];
for (NSString *imageName in imageFileNameArray) {
NSString *imagePath = [imageCacheDirPath stringByAppendingPathComponent:imageName];
[[NSFileManager defaultManager] removeItemAtPath:imagePath error:nil];
}
}
- (void)imageClick
{
if ([self.delegate respondsToSelector:@selector(circleScrollView:clickImageWithIndex:)]) {
[self.delegate circleScrollView:self clickImageWithIndex:self.currIndex];
}
}
@end
demo的下载地址 吻我😄😄😄
网友评论