美文网首页
两个ImageView实现轮播图

两个ImageView实现轮播图

作者: charlotte2018 | 来源:发表于2017-04-07 13:43 被阅读75次

1. 轮播图有用CollectionView实现的,如SDCycleScrollView github地址:https://github.com/gsdios/SDCycleScrollView

2. 这次用scrollView实现下,假如有1000张图片需要轮播,我们不可能在scrollView上放1000个ImageView吧,那样性能和内存就没法保证了。所以得想办法复用。采用scrollView上放两个ImageView实现轮播图。是一件多么美好的事情啊😄😄。层级结构:

1429074-956225c7acc72a34.png

3.位置

  • 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的下载地址 吻我😄😄😄

相关文章

  • iOS高效图片轮播 - 两个imageView实现

    iOS高效图片轮播 - 两个imageView实现 iOS高效图片轮播 - 两个imageView实现

  • 两个ImageView实现轮播图

    1. 轮播图有用CollectionView实现的,如SDCycleScrollView github地址:htt...

  • iOS无限轮播图 无限复用

    关于轮播图的实现, zz所了解到的有三种: 利用scrollView根据轮播图片的多少来创建imageview 然...

  • 2018-03-08

    Android自定义HorizontalScrollView和ImageView实现不一样的轮播图效果 需求效果 ...

  • 3个imageView实现轮播图

    撸了一个轮播图,已上传github(今天github提交好慢,微软你干了什么。。。) → 传送门 使用方法: 1...

  • 用两个ImageView实现图片的轮播

    在很多应用中我们都可以看到图片轮播器 下来我将使用两个imageView实现图片的轮播,也是目前我用到最简单的方法...

  • 两个imageView实现图片轮播

    因为原来面试的时候,被问到过这个问题,当时确实没有考虑过这个问题,然后就去网上找了一些大神的思路看了下,自己试着写...

  • 轮播图心得

    轮播图 写轮播图之前我们要认识到几个问题:一、什么是轮播图?二、怎么实现轮播效果?三、轮播图还有什么小功能可以实现...

  • 高效图片轮播,两个ImageView实现

    导语 在不少项目中,都会有图片轮播这个功能,现在网上关于图片轮播的框架层出不穷,千奇百怪,笔者根据自己的思路,用两...

  • 轮播图实现

    轮播图在实际应用开发使用较多,本文说明一下具体的实现过程。 一、实现轮播图的基本控件介绍。实现轮播图需要将多张图片...

网友评论

      本文标题:两个ImageView实现轮播图

      本文链接:https://www.haomeiwen.com/subject/mrncattx.html