WSLScrollView功能描述:這是在繼承UIView的基礎上利用UIScrollerView進行了封裝,支持循環(huán)輪播、自動輪播、自定義時間間隔、圖片間隔、當前頁碼和圖片大小,采用Block返回當前頁碼和處理當前點擊事件的一個View。

直接上總的效果圖,需要或感興趣的各路大神朋友請指教:

①、首先像往常一樣寫一個基本的UIScrollerView,會得到下圖:
_scrollerView = [[UIScrollView alloc] init];
_scrollerView.frame = CGRectMake((SELF_WIDTH - _currentPageSize.width) / 2, 0, _currentPageSize.width, _currentPageSize.height);
_scrollerView.delegate = self;
_scrollerView.pagingEnabled = YES;
_scrollerView.showsHorizontalScrollIndicator = NO;
[self addSubview:_scrollerView];

然后設置我們通常會忽略UIScrollerView的一個屬性clipsToBounds為NO,默認是Yes,你會看到_scrollerView其它部分相鄰的圖片,但是你會發(fā)現(xiàn)那部分相鄰的圖片不會響應在它上面的任何觸摸事件,因為那部分子視圖超出了它的父視圖,可以用響應鏈機制解決這個問題:
_scrollerView.clipsToBounds = NO;
//處理超過父視圖部分不能點擊的問題,重寫UIView里的這個方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if ([self pointInside:point withEvent:event]) {
CGPoint newPoint = [_scrollerView convertPoint:point fromView:self];
for (UIImageView * imageView in _scrollerView.subviews) {
if (CGRectContainsPoint(imageView.frame, newPoint)) {
CGPoint newSubViewPoint = [imageView convertPoint:point fromView:self];
return [imageView hitTest:newSubViewPoint withEvent:event];
}
}
}
return nil;
}

②、接下來實現(xiàn)循環(huán)的功能:我相信好多人也都會想到 《 4 + 0 - 1 - 2 - 3 - 4 + 0 》這個方案,也就是先在數(shù)組的最后插入原數(shù)組的第一個元素,再在第一個位置插入原數(shù)組的最后一個元素;得到如下圖效果:(注意看:第一個向最后一個,最后向第一個循環(huán)過渡的時候有個Bug哦)
self.imageArray = [NSMutableArray arrayWithArray:_images];
[self.imageArray addObject:_images[0]];
[self.imageArray insertObject:_images.lastObject atIndex:0];
//初始化時的x偏移量要向前多一個單位的_currentPageSize.width
_scrollerView.contentOffset = CGPointMake(_currentPageSize.width * (self.currentPageIndex + 1), 0);

解決上述Bug的方案就是利用UIScrollView的兩個代理方法;在前后循環(huán)過渡處,剛開始拖拽時就在Bug的位置畫上對應的視圖;即《 3 + 4 + 0 - 1 - 2 - 3 - 4 + 0 + 1》,結束拖拽之后,再改變UIScrollView的contentOffset,不帶動畫;
//開始拖拽時執(zhí)行
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
//開始拖拽時停止計時器
[self.timer invalidate];
self.timer = nil;
// 3 + 4 + 0 - 1 - 2 - 3 - 4 + 0 + 1
NSInteger index = scrollView.contentOffset.x/_currentPageSize.width;
//是為了解決循環(huán)滾動的連貫性問題
if (index == 1) {
[self.scrollerView addSubview:self.lastView];
}
if (index == self.imageArray.count - 2) {
[self.scrollerView addSubview:self.firstView];
}
}
//結束拖拽時執(zhí)行
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
NSInteger index = scrollView.contentOffset.x/_currentPageSize.width;
//停止拖拽時打開計時器
if (_isTimer) {
[self statrScroll:_second];
}
//是為了解決循環(huán)滾動的連貫性問題
if (index == 0) {
scrollView.contentOffset = CGPointMake(_currentPageSize.width * (self.imageArray.count - 2) , 0);
}
if (index == self.imageArray.count - 1) {
scrollView.contentOffset = CGPointMake(_currentPageSize.width , 0);
}
}
③實現(xiàn)定時器自動循環(huán)輪播功能,需要解決的問題就是首尾過渡的時候,
如下圖所示:解決的思路和上述類似,主要代碼已標明→WSLScrollView

- (void)statrScroll:(CGFloat)second{
if (_timer == nil && _isTimer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:second target:self selector:@selector(autoNextPage) userInfo:nil repeats:YES];
}
}
- (void)autoNextPage{
[_scrollerView setContentOffset:CGPointMake( _currentPageSize.width * (_currentPageIndex + 1 + 1), 0) animated:YES];
if (_currentPageIndex + 2 == self.imageArray.count - 1) {
//是為了解決自動滑動到最后一頁再從頭開始的連貫性問題
[_scrollerView addSubview:self.firstView];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat index = scrollView.contentOffset.x/_currentPageSize.width;
if (index == 0 ) {
_currentPageIndex = self.imageArray.count - 1- 2;
}else if(index < 1){
}else if(index == self.imageArray.count - 1 || index == 1){
_currentPageIndex = 0;
//是為了解決自動滑動到最后一頁再從頭開始的連貫性問題
[_scrollerView setContentOffset:CGPointMake( _currentPageSize.width , 0) animated:NO];
}else if(index == ceil(index)){
_currentPageIndex = index - 1 ;
}
if (self.scrollEndBlock != nil) {
self.scrollEndBlock(_currentPageIndex);
}
}
