1. 程式人生 > >iOS輪播圖廣告圖

iOS輪播圖廣告圖

iOS介面上經常見到無限輪播圖,n張圖片輪流播放。 
下面給出一個解決方案和demo(https://github.com/zhengwenming/WMBannerView)。 
demo可設定輪播時間,可輪播本地和網路圖片(可設定預設的placeholder),支援手動和自動無限迴圈輪播。 
滾動輪播圖 
思路是這樣的,我們做一個WMBannerView繼承UIView,給出初始化方法, 
-(instancetype)initWithFrame:(CGRect)frame withURLArrayOrImagesArray:(NSArray *)dataArray; 
這個初始化方法會傳進去一個數組,這個數組裡面可以放本地的UIImage物件,也可以放網路上圖片的URL。這個WMBannerView裡面有一個UIScrollView,用這個UIScrollView去不斷的載入上中下這三個imageView。到達最後一個iamge的時候,再滑動就載入第一個,如果反過來滑動到第一個圖片,再滑動,就載入最後一個ImageView。具體的看程式碼實現。 
.h檔案裡的程式碼: 
#import < UIKit/UIKit.h>

typedef NS_ENUM(NSInteger,WMPageContolAlignment) { 
WMPageContolAlignmentCenter, /*< 滾動點居中 
/* */ 
WMPageContolAlignmentRight, /*< 滾動點居右 
/* */ 
WMPageContolAlignmentNone /*< 滾動點隱藏 
};

typedef void(^TapActionBlock)(NSInteger index);

@interface WMBannerView : UIView

/* 播放週期,預設五秒鐘 如設定0則不播放 */ 
@property(nonatomic,assign)NSTimeInterval animationDuration; 
/* 滾動點對齊方式,預設居中 */ 
@property(nonatomic,assign)WMPageContolAlignment pageControlAlignment;

/* 預設圖片,下載未完成時顯示 網路圖片的時候設定*/ 
/* 注意:賦值必須寫在Start方法之前,否則仍然為nil */ 
@property(nonatomic,strong)UIImage *placeHoldImage;

/* 資料來源 **/ 
@property(nonatomic,copy)NSArray *dataArray;

/** 
* 初始化廣告播放滾動View 

* @param rect 尺寸位置 
* @param dataArray 圖片資料來源 
*/ 
-(instancetype)initWithFrame:(CGRect)frame withURLArrayOrImagesArray:(NSArray *)dataArray; 
/** 
* 開始播放,預設五秒鐘,點選響應block回撥 

* @param block 回撥,返回當前圖片index,不需要回調則設定為nil 
*/ 
- (void)startWithTapActionBlock:(TapActionBlock)block;

/** 
* 停止播放 
*/ 
- (void)stop; 
@end

再看.m實現檔案裡面的程式碼 
依賴庫為SDWebImage 
#import “UIImageView+WebCache.h” 
#import “WMBannerView.h”

@interface WMBannerView () 
//容器 
@property(nonatomic,strong)UIScrollView *scrollView; 
/* 滾動圓點 **/ 
@property(nonatomic,strong)UIPageControl *pageControl; 
/* 定時器 **/ 
@property(nonatomic,strong)NSTimer *animationTimer; 
/* 當前index **/ 
@property(nonatomic,assign)NSInteger currentPageIndex; 
/* 所有的圖片陣列 **/ 
@property(nonatomic,strong)NSMutableArray *imageArray; 
/* 當前圖片陣列,永遠只儲存三張圖 **/ 
@property(nonatomic,strong)NSMutableArray *currentArray; 
/* block方式接收回調 */ 
@property(nonatomic,copy)TapActionBlock block; 
@end

@implementation WMBannerView

-(instancetype)initWithFrame:(CGRect)frame withURLArrayOrImagesArray:(NSArray *)dataArray{ 
self = [super initWithFrame:frame]; 
if (self) { 
self.dataArray = dataArray; 
self.autoresizesSubviews = YES; 
self.scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 
self.scrollView.contentMode = UIViewContentModeCenter; 
self.scrollView.contentSize = CGSizeMake(3 *frame.size.width, frame.size.height); 
self.scrollView.delegate = self; 
self.scrollView.contentOffset = CGPointMake(frame.size.width, 0); 
self.scrollView.pagingEnabled = YES; 
self.scrollView.showsHorizontalScrollIndicator = NO; 
self.scrollView.showsVerticalScrollIndicator = NO; 
[self addSubview:self.scrollView];

    //設定分頁顯示的圓點
    _pageControl = [[UIPageControl alloc] init];
    _pageControl.alpha = 0.8;
    _pageControl.currentPageIndicatorTintColor = [UIColor redColor];
    _pageControl.pageIndicatorTintColor = [UIColor whiteColor];
    [self addSubview:_pageControl];

    //點選事件
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
    [self addGestureRecognizer:tapGesture];

    //預設五秒鐘迴圈播放
    self.animationDuration = 5;
    //預設居中
    self.pageContolAliment = WMPageContolAlignmentCenter;
    //預設第一張
    self.currentPageIndex = 0;
}
return self;

}

-(void)layoutSubviews{ 
[super layoutSubviews]; 
self.scrollView.frame = self.bounds; 
}

-(void)setPageContolAliment:(WMPageContolAlignment)pageContolAliment{ 
_pageControlAlignment = pageContolAliment; 
_pageControl.hidden = NO; 
switch (pageContolAliment) { 
case WMPageContolAlignmentCenter: 

_pageControl.frame = CGRectMake(0, CGRectGetHeight(self.scrollView.frame) - 20, CGRectGetWidth(self.scrollView.frame), 10); 

break; 
case WMPageContolAlignmentRight: 

CGSize size = CGSizeMake(self.dataArray.count * 10 * 1.2, 10); 
CGFloat x = self.scrollView.frame.size.width - size.width - 10; 
CGFloat y = self.scrollView.frame.size.height - 20; 
_pageControl.frame = CGRectMake(x, y, size.width, size.height); 

break; 
case WMPageContolAlignmentNone: 
_pageControl.hidden = YES; 
break;

    default:
        break;
}

}

-(void)setAnimationDuration:(NSTimeInterval)animationDuration{ 
_animationDuration = animationDuration;

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

if (animationDuration <= 0) {
    return;
}

self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:_animationDuration
                                                       target:self
                                                     selector:@selector(animationTimerDidFired:)
                                                     userInfo:nil
                                                      repeats:YES];

[self.animationTimer setFireDate:[NSDate distantFuture]];

}

-(void)downLoadImage{ 
if (self.dataArray && self.dataArray.count > 0) { 
if ([self.dataArray.firstObject respondsToSelector:@selector(hasPrefix:)]) { 
if ([self.dataArray.firstObject hasPrefix:@”http”]) {//網路圖片 
self.imageArray = [NSMutableArray array]; 
__weak typeof(self) weak = self; 
[self.dataArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 
UIImageView *imageView = [[UIImageView alloc]initWithFrame:self.scrollView.frame]; 
[imageView sd_setImageWithURL:[NSURL URLWithString:obj] placeholderImage:self.placeHoldImage]; 
[weak.imageArray addObject:imageView]; 
}]; 
_pageControl.numberOfPages = self.dataArray.count; 
[self configContentViews];

        }
    }
    else{//本地圖片
        self.imageArray = [NSMutableArray array];
        __weak typeof(self) weak = self;
        [self.dataArray enumerateObjectsUsingBlock:^(UIImage *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            UIImageView *imageView = [[UIImageView alloc]initWithFrame:self.scrollView.frame];
            imageView.image = obj;
            [weak.imageArray addObject:imageView];
        }];
        _pageControl.numberOfPages = self.dataArray.count;
        [self configContentViews];
    }
}

}

#pragma mark - 私有函式

  • (void)configContentViews 

    [self.scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

    NSInteger previousPageIndex = [self getValidNextPageIndexWithPageIndex:_currentPageIndex - 1]; 
    NSInteger rearPageIndex = [self getValidNextPageIndexWithPageIndex:_currentPageIndex + 1];

    self.currentArray = (_currentArray?:[NSMutableArray new]);

    _currentArray.count == 0 ?:[_currentArray removeAllObjects];

    if (_imageArray) { 
    if (_imageArray.count >= 3) { 
    [_currentArray addObject:_imageArray[previousPageIndex]]; 
    [_currentArray addObject:_imageArray[_currentPageIndex]]; 
    [_currentArray addObject:_imageArray[rearPageIndex]]; 

    else{ 
    [self getImageFromArray:_imageArray[previousPageIndex]]; 
    [self getImageFromArray:_imageArray[_currentPageIndex]]; 
    [self getImageFromArray:_imageArray[rearPageIndex]]; 

    }

    [_currentArray enumerateObjectsUsingBlock:^(UIImageView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 
    obj.userInteractionEnabled = YES; 
    CGRect rightRect = obj.frame; 
    rightRect.origin = CGPointMake(CGRectGetWidth(self.frame) * idx, 0); 
    obj.frame = rightRect; 
    [self.scrollView addSubview:obj]; 
    }];

    [self.scrollView setContentOffset:CGPointMake(CGRectGetWidth(self.scrollView.frame), 0)]; 
    }

  • (NSInteger)getValidNextPageIndexWithPageIndex:(NSInteger)currentPageIndex; 

    if(currentPageIndex == -1){ 
    return self.dataArray.count - 1; 

    else if (currentPageIndex == self.dataArray.count){ 
    return 0; 

    else 
    return currentPageIndex; 
    }

/** 
* 解決小於三個圖片顯示的bug 
* @param imageView 原始圖 
*/ 
-(void)getImageFromArray:(UIImageView *)imageView{ 
//開闢自動釋放池 
@autoreleasepool { 
UIImageView *tempImage = [[UIImageView alloc]initWithFrame:imageView.frame]; 
tempImage.image = imageView.image; 
[_currentArray addObject:tempImage]; 

}

#pragma mark - UIScrollViewDelegate
  • (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 

    [self.animationTimer setFireDate:[NSDate distantFuture]]; 
    }

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

    [self.animationTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:self.animationDuration]]; 
    }

  • (void)scrollViewDidScroll:(UIScrollView *)scrollView 

    int contentOffsetX = scrollView.contentOffset.x; 
    if(contentOffsetX >= (2 * CGRectGetWidth(scrollView.frame))) { 
    self.currentPageIndex = [self getValidNextPageIndexWithPageIndex:self.currentPageIndex + 1]; 
    _pageControl.currentPage = _currentPageIndex; 
    [self configContentViews]; 

    if(contentOffsetX <= 0) { 
    self.currentPageIndex = [self getValidNextPageIndexWithPageIndex:self.currentPageIndex - 1]; 
    _pageControl.currentPage = _currentPageIndex; 
    [self configContentViews]; 
    }

}

  • (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 

    [scrollView setContentOffset:CGPointMake(CGRectGetWidth(scrollView.frame), 0) animated:YES]; 
    }

    pragma mark - 迴圈事件

  • (void)animationTimerDidFired:(NSTimer *)timer 

    CGPoint newOffset = CGPointMake(self.scrollView.contentOffset.x + CGRectGetWidth(self.scrollView.frame), self.scrollView.contentOffset.y); 
    [self.scrollView setContentOffset:newOffset animated:YES]; 
    }

    pragma mark - 響應事件

  • (void)tap 

    if (self.block) { 
    self.block(self.currentPageIndex); 

    }

    pragma mark - 開始滾動

    -(void)startWithTapActionBlock:(TapActionBlock)block{ 
    [self.animationTimer setFireDate:[NSDate date]];

    [self downLoadImage];

    self.block = block; 
    }

    pragma mark - 停止滾動

    -(void)stop{ 
    [self.animationTimer invalidate]; 
    }

  • (void)dealloc 

    self.animationTimer = nil; 
    self.imageArray = nil; 
    self.dataArray = nil; 
    self.scrollView = nil; 
    }

@end

用法

那麼做好我們的輪播圖WMBannerView了,現在開始用了

WMBannerView * wmView = [[WMBannerView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width*3/4) withURLArrayOrImagesArray:URLArray]; 
wmView.pageControlAlignment = WMPageContolAlignmentCenter; 
wmView.placeHoldImage = [UIImage imageNamed:@”placeholderImage”]; 
wmView.animationDuration = 1.0;//設定滾動的時間間隔,為0的時候不自動滾動 
//點選圖片的回撥block,可以知道點選的index 
[wmView startWithTapActionBlock:^(NSInteger index) { 
NSLog(@”點選了第%@張”,@(index)); 
}];

然後放置到tableView的tableHeaderView上面

table = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain]; 
table.dataSource = self; 
table.delegate = self; 
table.tableHeaderView = wmView; 
table.tableFooterView = [UIView new]; 
[self.view addSubview:table];

Demo地址

 
描述:強大的廣告輪播圖,可設定輪播時間,可輪播本地和網路圖片(可設定預設的placeholder),支援手動和自動無限迴圈輪播。可放到UITableView頭上,也可以放置到UICollectionView的頭上。