iOS實(shí)現(xiàn)無(wú)限循環(huán)輪播圖效果
本文實(shí)例為大家分享了iOS實(shí)現(xiàn)無(wú)限循環(huán)輪播圖的具體代碼,供大家參考,具體內(nèi)容如下
輪播圖基礎(chǔ)控件,左滑右滑都能無(wú)限循環(huán)
預(yù)覽

思路
(1)在第一張左邊加一張最后一張的圖片,往左滑到邊緣結(jié)束后計(jì)算偏移量迅速定位成最后一張

#pragma mark - pagecontrol事件
// 這個(gè)是點(diǎn)擊小圓點(diǎn)條進(jìn)行切換,到邊不能循環(huán)
- (void)pageControlTouched
{
// 點(diǎn)擊的時(shí)候停止計(jì)時(shí)
[self.kvTimer setFireDate:[NSDate distantFuture]];
// 滑到指定頁(yè)面
NSInteger curPageIdx = _pageControl.currentPage;
CGFloat offsetX = self.frame.size.width * (curPageIdx + 1);
[self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
// 重新開啟定時(shí)器
[self.kvTimer setFireDate:[NSDate dateWithTimeInterval:kTimerInterval sinceDate:[NSDate date]]];
}
#pragma mark - 滾動(dòng)事件
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// printf("start drag\n");
// 記錄偏移量
preOffsetX = scrollView.contentOffset.x;
// 開始手動(dòng)滑動(dòng)時(shí)暫停定時(shí)器
[self.kvTimer setFireDate:[NSDate distantFuture]];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
// printf("end drag\n");
// 左右邊界
CGFloat leftEdgeOffsetX = 0;
CGFloat rightEdgeOffsetX = self.frame.size.width * (_pageCount + 1);
if (scrollView.contentOffset.x < preOffsetX)
{
// 左滑
if (scrollView.contentOffset.x > leftEdgeOffsetX)
{
self.pageControl.currentPage = scrollView.contentOffset.x / self.frame.size.width - 1;
}
else if (scrollView.contentOffset.x == leftEdgeOffsetX)
{
self.pageControl.currentPage = _pageCount - 1;
}
if (scrollView.contentOffset.x == leftEdgeOffsetX)
{
self.scrollView.contentOffset = CGPointMake(self.frame.size.width * _pageCount, 0);
}
}
else
{
// 右滑
// 設(shè)置小點(diǎn)
if (scrollView.contentOffset.x < rightEdgeOffsetX)
{
self.pageControl.currentPage = scrollView.contentOffset.x / self.frame.size.width - 1;
}
else if (scrollView.contentOffset.x == rightEdgeOffsetX)
{
self.pageControl.currentPage = 0;
}
// 滑動(dòng)完了之后從最后多余頁(yè)趕緊切換到第一頁(yè)
if (scrollView.contentOffset.x == rightEdgeOffsetX)
{
self.scrollView.contentOffset = CGPointMake(self.frame.size.width, 0);
}
}
// 結(jié)束后又開啟定時(shí)器
[self.kvTimer setFireDate:[NSDate dateWithTimeInterval:kTimerInterval sinceDate:[NSDate date]]];
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
// printf("end scroll\n");
}
#pragma mark - 定時(shí)器控制的滑動(dòng)
// 往右邊滑
- (void)changePageRight
{
// 設(shè)置當(dāng)前需要偏移的量,每次遞增一個(gè)page寬度
CGFloat offsetX = _scrollView.contentOffset.x + CGRectGetWidth(self.frame);
// 根據(jù)情況進(jìn)行偏移
CGFloat edgeOffsetX = self.frame.size.width * (_pageCount + 1); // 最后一個(gè)多余頁(yè)面右邊緣偏移量
// 從多余頁(yè)往右邊滑,趕緊先設(shè)置為第一頁(yè)的位置
if (offsetX > edgeOffsetX)
{
// 偏移量,不帶動(dòng)畫,欺騙視覺
self.scrollView.contentOffset = CGPointMake(self.frame.size.width, 0);
// 這里提前改變下一個(gè)要滑動(dòng)到的位置為第二頁(yè)
offsetX = self.frame.size.width * 2;
}
// 帶動(dòng)畫滑動(dòng)到下一頁(yè)面
[self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
if (offsetX < edgeOffsetX)
{
self.pageControl.currentPage = offsetX / self.frame.size.width - 1;
}
else if (offsetX == edgeOffsetX)
{
// 最后的多余那一頁(yè)滑過(guò)去之后設(shè)置小點(diǎn)為第一個(gè)
self.pageControl.currentPage = 0;
}
}
// 往左邊滑
- (void)changePageLeft
{
// 設(shè)置當(dāng)前需要偏移的量,每次遞減一個(gè)page寬度
CGFloat offsetX = _scrollView.contentOffset.x - CGRectGetWidth(self.frame);
// 根據(jù)情況進(jìn)行偏移
CGFloat edgeOffsetX = 0; // 最后一個(gè)多余頁(yè)面左邊緣偏移量
// 從多余頁(yè)往左邊滑動(dòng),先設(shè)置為最后一頁(yè)
if (offsetX < edgeOffsetX)
{
self.scrollView.contentOffset = CGPointMake(self.frame.size.width * _pageCount, 0);
offsetX = self.frame.size.width * (_pageCount - 1);
}
// 帶動(dòng)畫滑動(dòng)到前一頁(yè)面
[self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
if (offsetX > edgeOffsetX)
{
self.pageControl.currentPage = offsetX / self.frame.size.width - 1;
}
else if (offsetX == edgeOffsetX)
{
// 最后的多余那一頁(yè)滑過(guò)去之后設(shè)置小點(diǎn)為最后一個(gè)
self.pageControl.currentPage = _pageCount - 1;
}
}
(2)總共只有左、中、右三個(gè)頁(yè)面,每次滑動(dòng)后重新進(jìn)行數(shù)據(jù)跟頁(yè)面的關(guān)聯(lián)

#pragma mark - 定時(shí)器回調(diào)
- (void)changePageRight
{
// 往右滑并且設(shè)置小圓點(diǎn),永遠(yuǎn)都是滑到第三頁(yè)
[_scrollView setContentOffset:CGPointMake(self.frame.size.width * 2, 0) animated:YES];
[self resetPageIndex:YES];
}
- (void)changePageLeft
{
// 往左滑,永遠(yuǎn)都是滑動(dòng)到第一頁(yè)
[_scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
[self resetPageIndex:NO];
}
#pragma mark - 重新設(shè)置索引和頁(yè)面圖片
- (void)resetPageIndex:(BOOL)isRight
{
if (isRight)
{
// 根據(jù)之前的page下標(biāo)來(lái)修改
if (_prePageIndex == _pageCount - 1)
{
// 到頭了就回到第一個(gè)
_pageControl.currentPage = 0;
}
else
{
// 這里用_prePageIndex來(lái)算,否則點(diǎn)擊小圓點(diǎn)條會(huì)重復(fù)計(jì)算了
_pageControl.currentPage = _prePageIndex + 1;
}
}
else
{
if (_prePageIndex == 0)
{
_pageControl.currentPage = _pageCount - 1;
}
else
{
_pageControl.currentPage = _prePageIndex - 1;
}
}
_prePageIndex = _pageControl.currentPage;
}
- (void)resetPageView
{
// 每次滑動(dòng)完了之后又重新設(shè)置當(dāng)前顯示的page時(shí)中間的page
UIImageView *leftPage = [_scrollView viewWithTag:1000];
UIImageView *middlePage = [_scrollView viewWithTag:1001];
UIImageView *rightPage = [_scrollView viewWithTag:1002];
if (_pageControl.currentPage == _pageCount - 1)
{
// n- 1 -> n -> 0
leftPage.image = _kvImageArray[_pageControl.currentPage - 1];
middlePage.image = _kvImageArray[_pageControl.currentPage];
rightPage.image = _kvImageArray.firstObject;
}
else if (_pageControl.currentPage == 0)
{
// n -> 0 -> 1
// 到尾部了,改成從頭開始
leftPage.image = _kvImageArray.lastObject;
middlePage.image = _kvImageArray.firstObject;
rightPage.image = _kvImageArray[1];
}
else
{
// x - 1 -> x -> x + 1
leftPage.image = _kvImageArray[_pageControl.currentPage - 1];
middlePage.image = _kvImageArray[_pageControl.currentPage];
rightPage.image = _kvImageArray[_pageControl.currentPage + 1];
}
// 重新設(shè)置偏移量
_scrollView.contentOffset = CGPointMake(self.frame.size.width, 0);
}
#pragma mark - pagecontrol事件
- (void)pageControlTouched
{
[self stopTimer];
NSInteger curPageIndex = _pageControl.currentPage;
if (curPageIndex > _prePageIndex)
{
// 右滑
[self changePageRight];
}
else
{
// 左滑
[self changePageLeft];
}
[self startTimer];
}
#pragma mark - scrollview滑動(dòng)代理
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// 先停掉定時(shí)器
[self stopTimer];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
// 手動(dòng)拖拽滑動(dòng)結(jié)束后
if (scrollView.contentOffset.x > self.frame.size.width)
{
// 右滑
[self resetPageIndex:YES];
}
else
{
// 左滑
[self resetPageIndex:NO];
}
[self resetPageView];
// 開啟定時(shí)器
[self startTimer];
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
// 自動(dòng)滑動(dòng)結(jié)束后重新設(shè)置圖片
[self resetPageView];
}
源代碼下載
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS開發(fā)教程之UIView和UIViewController的生命周期詳解
UIViewController是IOS程序中的一個(gè)重要組成部分,下面這篇文章主要給大家介紹了關(guān)于iOS開發(fā)教程之UIView和UIViewController的生命周期的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-04-04
iOS使用UICollectionView實(shí)現(xiàn)橫向滾動(dòng)照片效果
這篇文章主要為大家詳細(xì)介紹了iOS使用UICollectionView實(shí)現(xiàn)橫向滾動(dòng)照片效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
iOS如何固定UITableView中cell.imageView.image的圖片大小
這篇文章主要給大家介紹了關(guān)于iOS如何固定UITableView中cell.imageView.image圖片大小的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位iOS開發(fā)者們的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11
Objective-C關(guān)鍵字@property使用原理探究
這篇文章主要為大家介紹了Objective-C關(guān)鍵字@property使用原理探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
ios啟動(dòng)頁(yè)強(qiáng)制豎屏(進(jìn)入App后允許橫屏與豎屏)
最近工作遇到這樣一個(gè)需要,當(dāng)進(jìn)入啟動(dòng)頁(yè)需要強(qiáng)制豎屏,而進(jìn)入APP后就允許橫屏與豎屏,通過(guò)查找相關(guān)的資料找到了解決的方法,所以將實(shí)現(xiàn)的方法整理后分享出來(lái),需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。2017-03-03
IOS 中l(wèi)oadView,viewDidLoad,viewDidUnload詳解及使用
這篇文章主要介紹了IOS 中l(wèi)oadView,viewDidLoad,viewDidUnload詳解及使用的相關(guān)資料,需要的朋友可以參考下2017-02-02
iOS11 WKWebView內(nèi)容過(guò)濾規(guī)則詳解
本篇文章主要介紹了iOS11 WKWebView內(nèi)容過(guò)濾規(guī)則詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07

