第二十一篇、广告轮播器(支持循环滚动)

1.自定义UIPageControl控件

.h

#import <UIKit/UIKit.h>

@protocol CustomPageControlDelegate <NSObject>
@optional
- (void) selectedIndex:(NSInteger) index;

@end

@interface CustomPageControl : UIView

@property (nonatomic,assign) NSInteger numberOfPages;
@property (nonatomic,assign) NSInteger currentPage;
@property (nonatomic,assign) float PointSize; // 圆点的大小
@property (nonatomic,assign) float distanceOfPoint; // 两个圆点的距离
@property (nonatomic,assign) UIColor * currentPagePointColor; // 当前点的颜色
@property (nonatomic,assign) UIColor * pagePointColor; // 其它圆点的颜色
@property (nonatomic,strong) UIImage *currentImage; // 当前点的图片
@property (nonatomic,strong) UIImage *otherImage; // 其它点的图片
@property (nonatomic,weak) id<CustomPageControlDelegate> delegate;

-(float)sizeForNumberOfPages:(NSInteger)pages;
-(void)setNumberOfPages:(NSInteger)pages;
-(void)setCurrentPage:(NSInteger)page;

@end

 

.m

#import "CustomPageControl.h"
@interface CustomPageControl()
{

}
@end

@implementation CustomPageControl
@synthesize currentPage = _currentPage;
@synthesize numberOfPages = _numberOfPages;

#pragma mark--系统方法
- (id) initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}
 - (void) drawRect:(CGRect)rect
{
    //[super drawRect:rect];
    [self setCurrentPage:0]; // 这个如果不调用(首次加载不能显示,拖动了才显示)
}

#pragma mark--自定义方法 公有
-(float)sizeForNumberOfPages:(NSInteger)pages{
    return _distanceOfPoint*(pages+1) + _PointSize*pages;
}

- (void) setNumberOfPages:(NSInteger)pages
{
    // 居中
     CGFloat pointImageViewXFloat = (self.frame.size.width -_PointSize * pages - _distanceOfPoint * (pages - 1)) / 2.0;
    for (int i = 0; i < pages; i++) {
       
        UIImageView * pointImageView = [[UIImageView alloc] initWithFrame:CGRectMake(pointImageViewXFloat , (self.frame.size.height-_PointSize)/2.0, _PointSize, _PointSize)];
        
        pointImageView.layer.cornerRadius = _PointSize / 2.0; // 设置半径
        pointImageView.layer.masksToBounds = YES;
        pointImageView.tag = i;
        [self addSubview:pointImageView];
        
        // 添加点击手势
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(singleTap:)];
        pointImageView.userInteractionEnabled = YES;
        [pointImageView addGestureRecognizer:tap];
        pointImageViewXFloat +=  _PointSize + _distanceOfPoint ;
    }
}


- (void) setCurrentPage:(NSInteger)page
{
    NSInteger countOfPages = [self.subviews count];
    for (NSUInteger subviewIndex = 0; subviewIndex < countOfPages; subviewIndex++) {
        UIImageView* subview = [self.subviews objectAtIndex:subviewIndex];
        if (subviewIndex == page) {
            if (_currentImage && _otherImage)
            {
                 subview.image = _currentImage;
            }else
            {
                [subview setBackgroundColor:_currentPagePointColor];
            }
           
        }else{
            if (_currentImage && _otherImage)
            {
                subview.image = _otherImage;
            }
            else
            {
                [subview setBackgroundColor:_pagePointColor];
            }
            
            //subview.image = [UIImage imageNamed:@"point1"];
        }
    }
}
#pragma mark--自定义方法 私有
- (void) singleTap:(UITapGestureRecognizer *) tap
{
    if ([_delegate respondsToSelector:@selector(selectedIndex:)]) {
        [_delegate selectedIndex:tap.view.tag];
    }
}

@end

 

 

2.展示图片View

.h

#import <UIKit/UIKit.h>

// 用于判断pageControl显示的位置
typedef enum {
    isCenter, 
    isRight,
} contentType;

@protocol PictureCycleDelegate <NSObject>

@optional
/*
 @brief 点击回调
 @param view 当前点击的View
 @param index 当前选择的索引
 */
-(void) seletedView:(id) view index:(int) index;

@end

@interface PictureCycle : UIView

@property (weak,nonatomic) id<PictureCycleDelegate>delegate;

/*****
 **@param frame 当前view的frame
 **@param picArray 显示的图片数组
 **@param autoBOOL 是否允许自动轮播
 **@param type 去掉pageControl是居中还是居右
 *****/
- (id)initWithFrame:(CGRect)frame array:(NSMutableArray *)picArray Auto:(BOOL) autoBOOL contentType:(contentType) type; // 根据传入数组来初始化此view

// 移除定时器 ,如果是调用自动轮播,在外面需要调用(不然造成循环引用),不然不调用dealloc
- (void)removeTimer;

@end

 

.m

//
//  PictureCircle.m
//  Circle
//
//  Created by egood001 on 15/7/11.
//  Copyright (c) 2015年 lcy. All rights reserved.
//

#import "PictureCycle.h"
#import "CustomPageControl.h"
#import "MainNewsModel.h"
#import "BaseNetManager.h"

// 执行动画的时间
#define animationTime 1.2f
// 默认的加载图片
#define defaultImage [UIImage imageNamed:@"zwt"]

@interface PictureCycle ()<UIScrollViewDelegate,CustomPageControlDelegate>
{
    CGFloat currentWidthFloat;
    CGFloat currentHeightFloat;
    BOOL publicAutoBOOL; // 是否需要自动滚动查看
    contentType modeType;
    CGFloat noteViewHeightFloat;
}


@property (nonatomic, strong) UIScrollView * picScrollView; // 轮播图
@property (nonatomic, strong) CustomPageControl * pageControl; // 显示条
@property (nonatomic, strong) NSTimer * timer; // 定时器
@property (nonatomic, assign) NSInteger totalPicCount; // 总共多少个图片

@property (nonatomic, strong) UIImageView *currentImageView;
@property (nonatomic, strong) UIImageView *nextImageView;
@property (nonatomic, strong) UIImageView *onImageView;
@property (nonatomic, strong) UILabel *messageLaebl;

@property (nonatomic, strong) NSMutableArray *dataArray;
@property (nonatomic, assign) NSInteger currentPageIndex;

@end

@implementation PictureCycle

#pragma mark--懒加载

-(UIScrollView *) picScrollView
{
    if (! _picScrollView) {
        _picScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, currentWidthFloat, currentHeightFloat)];
        _picScrollView.showsHorizontalScrollIndicator = NO;
        _picScrollView.showsVerticalScrollIndicator = NO;
        _picScrollView.contentSize = CGSizeMake(3 * currentWidthFloat, 0);
        _picScrollView.contentOffset = CGPointMake(currentWidthFloat, 0);
        _picScrollView.pagingEnabled = YES;
        _picScrollView.delegate = self;
        _picScrollView.scrollEnabled = NO;
        _picScrollView.bounces = NO;
    }
    return _picScrollView;
}

-(UIImageView *) currentImageView
{
    if (! _currentImageView) {
        _currentImageView = [[UIImageView alloc]initWithFrame:CGRectMake(currentWidthFloat, 0, currentWidthFloat, currentHeightFloat)];
        _currentImageView.userInteractionEnabled = YES;
        _currentImageView.contentMode = UIViewContentModeScaleToFill;
        
        MainNewsModelList *list = [self.dataArray objectAtIndex:0];
        NSString *imageString = [NSString stringWithFormat:@"%@%@",TestURL,[BaseNetManager getOffRubbishWithString:list.img]];
        NSURL *url = [NSURL URLWithString:imageString];
        [_currentImageView sd_setImageWithURL:url placeholderImage:defaultImage];
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:) ];
        [_currentImageView addGestureRecognizer:tap];
    }
    return _currentImageView;
}

-(UIImageView *) onImageView
{
    if (! _onImageView) {
        _onImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, currentWidthFloat, currentHeightFloat)];
        _onImageView.contentMode = UIViewContentModeScaleToFill;
        _onImageView.userInteractionEnabled = YES;
         NSInteger imageIndex = self.dataArray.count == 1 ? 0 : self.dataArray.count - 1;
        MainNewsModelList *list = [self.dataArray objectAtIndex:imageIndex];
        NSString *imageString = [NSString stringWithFormat:@"%@%@",TestURL,[BaseNetManager getOffRubbishWithString:list.img]];
        NSURL *url = [NSURL URLWithString:imageString];
        [_onImageView sd_setImageWithURL:url placeholderImage:defaultImage];
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:) ];
        [_onImageView addGestureRecognizer:tap];
    }
    return _onImageView;
}

-(UIImageView *) nextImageView
{
    if (! _nextImageView) {
        _nextImageView = [[UIImageView alloc]initWithFrame:CGRectMake(2 * currentWidthFloat, 0, currentWidthFloat, currentHeightFloat)];
        _nextImageView.userInteractionEnabled = YES;
        _nextImageView.contentMode = UIViewContentModeScaleToFill;
        NSInteger imageIndex = self.dataArray.count == 1 ? 0 : 1;
        MainNewsModelList *list = [self.dataArray objectAtIndex:imageIndex];
        NSString *imageString = [NSString stringWithFormat:@"%@%@",TestURL,[BaseNetManager getOffRubbishWithString:list.img]];
        NSURL *url = [NSURL URLWithString:imageString];
        [_nextImageView sd_setImageWithURL:url placeholderImage:defaultImage];
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:) ];
        [_nextImageView addGestureRecognizer:tap];
    }
    return _nextImageView;
}

-(CustomPageControl *) pageControl
{
    if (! _pageControl) {
        CGFloat width=[UIScreen mainScreen].bounds.size.width;
        float pointSize = 12.0f; // 圆点的大小
        float pointToPointDistantWidth = 3.0f; // 两个圆点的距离
        
        float pageControlWidth = self.dataArray.count * (pointSize + pointToPointDistantWidth) + pointToPointDistantWidth *2;
        float pagecontrolHeight = 10;
        
        // 默认是居右
//        CGFloat pageControlXFloat = currentWidthFloat - pageControlWidth;
//        if (modeType == isCenter) {
//            pageControlXFloat = pageControlXFloat / 2.0;
//        }
        _pageControl = [[CustomPageControl alloc] initWithFrame:CGRectMake(width/2-pageControlWidth/2, (noteViewHeightFloat - pagecontrolHeight) / 2.0 + 10, pageControlWidth , pagecontrolHeight)];
        _pageControl.PointSize = pointSize;
        _pageControl.distanceOfPoint = pointToPointDistantWidth; // 点与点的距离
        _pageControl.currentPage = 0;
        _pageControl.numberOfPages = self.dataArray.count;
        _pageControl.currentPagePointColor = [UIColor redColor]; // 当前的颜色(还可以设置图片)
        _pageControl.pagePointColor = [UIColor grayColor];
        //[_pageControl setBackgroundColor:[UIColor grayColor]];
    }
    return _pageControl;
}

#pragma mark--rewrite system Method

/*****
 **@param frame 当前view的frame
 **@param picArray 显示的图片数组
 **@param autoBOOL 是否允许自动轮播
 **@param type 去掉pageControl是居中还是居右
 *****/
- (id)initWithFrame:(CGRect)frame array:(NSMutableArray *)picArray Auto:(BOOL)autoBOOL contentType:(contentType) type
{
    self = [super initWithFrame:frame];
    if (self) {
        currentWidthFloat = frame.size.width;
        currentHeightFloat = frame.size.height;
        publicAutoBOOL = autoBOOL;
        modeType = type;
        [self downLoadImages];
        [self setupScrollViewWithArray:picArray];
       // [self emptyDatatoFlag];
    }
    return self;
}


#pragma mark--system Methods


- (void) layoutSubviews
{
    [super layoutSubviews];
}

- (void)dealloc
{
    NSLog(@"adDealloc");
}

#pragma mark--private Methods

/*
 @brief 清除点击的标志
 */
- (void) emptyDatatoFlag
{
    [[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"Flag"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

/*
 * @brief 下载图片
 */
- (void)downLoadImages
{
    // 1.创建一个组
    dispatch_group_t group = dispatch_group_create();
    
    // MainNewsModelList *list = [self.dataArray objectAtIndex:0];
    for (MainNewsModelList *list in self.dataArray)
    {
        // 将当前的下载操作添加到组中
        dispatch_group_enter(group);
        
        NSString *imageString = [NSString stringWithFormat:@"%@%@",TestURL,[BaseNetManager getOffRubbishWithString:list.img]];
        NSURL *url = [NSURL URLWithString:imageString];
        
        [[SDWebImageManager sharedManager] downloadImageWithURL:url options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
            // 离开当前组
            dispatch_group_leave(group);
        }];
        
    }
    // 2.当所有图片都下载完毕
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        
        // 移除所有的子控件
        for (UIView *view in self.subviews) {
            [view removeFromSuperview];
        }
        self.picScrollView = nil;
        self.currentPageIndex = 0;
        [self removeTimer];
        // 重新添加子控件
        [self setupScrollViewWithArray:self.dataArray];
        
    });
    
}

- (void)setupScrollViewWithArray:(NSMutableArray *)picArray
{
    // 图片数
    if ( ! [picArray count]) {
        return;
    }
    
    self.dataArray = [NSMutableArray  arrayWithArray:picArray];
    
    NSInteger totalCount = self.dataArray.count;
    self.totalPicCount = totalCount;
    
    // 添加滚动视图
    [self addSubview:self.picScrollView];
    // 添加三张图片
    [_picScrollView addSubview:self.currentImageView];
    [_picScrollView addSubview:self.onImageView];
    [_picScrollView addSubview:self.nextImageView];

    
    // 可以在noteView添加titleLable
    UIView *noteView = [[UIView alloc] initWithFrame:CGRectMake(0, currentHeightFloat - 35, currentWidthFloat, 35)];
    noteView.backgroundColor = [UIColor clearColor];
    noteView.alpha = 0.75;
    //[UIColor clearColor];
    noteView.userInteractionEnabled = YES;
    [self addSubview:noteView];
    
    // 设置标题
  //  MainNewsModelList *list = [self.dataArray objectAtIndex:0];
    //UILabel *messageLabel = [[UILabel alloc]init];
    //messageLabel.backgroundColor = [UIColor redColor];
  //  messageLabel.frame = CGRectMake(0, 0, noteView.frame.size.width, noteView.frame.size.height);
   // messageLabel.text = list.title;
    //[noteView addSubview:messageLabel];
    //self.messageLaebl = messageLabel;
    
    noteViewHeightFloat = noteView.frame.size.height;
    
    if(1 < [picArray count])
    {
        if ( publicAutoBOOL ){
           [self addTimer];
        }
        [noteView addSubview:self.pageControl];
        [_picScrollView setScrollEnabled:YES]; // 当图片只有一张,禁止滚动
        
    }
    
}

// 单击手势监听
- (void)singleTap:(UITapGestureRecognizer *)tap
{
    
    if ([_delegate respondsToSelector:@selector(seletedView:index:)]) {
        [_delegate seletedView:tap.view index:(int)self.currentPageIndex];
    }
    
    NSLog(@"当前点击了%@",tap.view);

//    if (publicAutoBOOL)
//    {
//        if (self.dataArray.count > 1) { // 如果是轮播的状态,跳转其他页面,停止轮播,返回继续轮播
//            [self removeTimer];
//            [self addTimer];
////            [[NSUserDefaults standardUserDefaults] setObject:@"1" forKey:@"Flag"];
////            [[NSUserDefaults standardUserDefaults] synchronize];
//        }
//    }

}

// 添加定时器
- (void)addTimer
{
    _timer = [NSTimer scheduledTimerWithTimeInterval:3.5f target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
    NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
    [currentRunLoop addTimer:self.timer forMode:NSRunLoopCommonModes];
}

// 移除定时器
- (void)removeTimer
{
    if (self.timer != nil)
    {
        [self.timer invalidate];
        self.timer = nil;
    }
}

// 播放下一张图片
- (void)nextImage
{
    if (publicAutoBOOL)
    {
        if (self.dataArray.count > 1) {
                NSString *flagString =[[NSUserDefaults standardUserDefaults] valueForKey:@"Flag"];
                if ([flagString intValue]) {
                    [self removeTimer];
                    [self addTimer];
                    return;
                }
        }
    }
    
    CGPoint offset = _picScrollView.contentOffset;
    
    offset.x += self.frame.size.width;
    if (offset.x > self.frame.size.width * 2) {
        offset.x = self.frame.size.width;
    }
    
    [_picScrollView setContentOffset:offset animated:YES];
    
    [self removeTimer];
    [self addTimer];
    
}

#pragma mark--协议方法

#pragma mark--CostomPageControlDelegate
- (void) selectedIndex:(NSInteger)index
{

}
#pragma mark - scrollViewDelegate
// 已经拖动
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat scollViewW = scrollView.frame.size.width;
    CGFloat offsetX = scrollView.contentOffset.x;
    int pageInteger = floor((offsetX - scollViewW / 2) / scollViewW) + 1;
    
    if(pageInteger > 2)
    {
        //防止向右快速滑动出现空白
        CGPoint offset = scrollView.contentOffset;
        offset.x = self.frame.size.width * 2;
        [_picScrollView setContentOffset:offset animated:YES];
        return;
    }
    
    float offset = scrollView.contentOffset.x;
    MainNewsModelList *list;
    if (_nextImageView.image == nil || _onImageView.image == nil) {
        
        //加载下一个视图
        NSInteger imageIndex = self.currentPageIndex >= _dataArray.count - 1 ? 0 : self.currentPageIndex + 1;
        list = [self.dataArray objectAtIndex:imageIndex];
        NSString *imageUrlString = [NSString stringWithFormat:@"%@%@",TestURL,[BaseNetManager getOffRubbishWithString:list.img]];
        NSURL *imageUrl = [NSURL URLWithString:imageUrlString];
        
        [_nextImageView sd_setImageWithURL:imageUrl placeholderImage:defaultImage];
        
        
        //加载上一个视图
        imageIndex = self.currentPageIndex == 0 ? self.dataArray.count - 1 : self.currentPageIndex - 1;
        list = [self.dataArray objectAtIndex:imageIndex];
        imageUrlString = [NSString stringWithFormat:@"%@%@",TestURL,[BaseNetManager getOffRubbishWithString:list.img]];
        imageUrl = [NSURL URLWithString:imageUrlString];
        
        [_onImageView sd_setImageWithURL:imageUrl placeholderImage:defaultImage];
        
    }
    
    if (offset == 0) { // 向左边滑动
        _currentImageView.image = _onImageView.image;
        scrollView.contentOffset = CGPointMake(scrollView.frame.size.width, 0);
        _onImageView.image = nil;
        
        if (self.currentPageIndex == 0) {
            self.currentPageIndex = self.dataArray.count - 1;
        }else{
            self.currentPageIndex -= 1;
        }
        
    }
    
    if (offset == scrollView.frame.size.width * 2) { // 右边滑动
        _currentImageView.image = _nextImageView.image;
        scrollView.contentOffset = CGPointMake(scrollView.frame.size.width, 0);
        _nextImageView.image = nil;
        
        if (self.currentPageIndex == self.dataArray.count - 1) {
            self.currentPageIndex = 0;
        }else{
            self.currentPageIndex += 1;
        }
        
    }
    
    [UIView animateWithDuration:0.3f animations:^{
            _pageControl.currentPage = self.currentPageIndex ;
        }];

    list = [self.dataArray objectAtIndex:self.currentPageIndex];
    self.messageLaebl.text = list.title;
}

// 将要拖动
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    if (publicAutoBOOL) {
        if (self.dataArray.count > 1) {
            //[self emptyDatatoFlag];
            [self removeTimer];
        }
    }
}

// 拖动完成
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    if (publicAutoBOOL) {
        if (self.dataArray.count > 1) {
            [self addTimer];
        }
    }
}




@end

 

posted on 2016-08-29 15:50  久冬不雨  阅读(251)  评论(0编辑  收藏  举报