
輪播圖.gif
無限輪播的實(shí)現(xiàn)思路
輪播圖最核心的部分是如何實(shí)現(xiàn)無限輪播。我的實(shí)現(xiàn)方式是:
在UIScrollView上添加三個(gè)UIImageView,要想達(dá)到無限輪播的效果,就要在任何停止?jié)L動(dòng)的時(shí)候(只展示一張完整圖片的時(shí)候),scrollView.contentOffset.x 都應(yīng)該等于輪播圖寬度,即處于中間圖片的位置,這樣就能保證處在每一張圖的位置時(shí),左右都可以滑動(dòng)。
代碼的實(shí)現(xiàn)是,在 scrollViewDidScroll 代理方法中,判斷當(dāng)scrollView滾動(dòng)到最左或者最右的極限位置時(shí),立即將scrollView.contentOffset.x設(shè)置為輪播圖寬度,即恢復(fù)到中間位置;
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let contentOffsetX = scrollView.contentOffset.x
// 設(shè)置圖片信息(滑到最左邊或者最右邊的時(shí)候,立即回正,同時(shí)改變圖片,不會造成視覺上的誤差)
if contentOffsetX == 2 * scrollView.frame.width {// 左滑
currentIndex = getActualCurrentPage(calculatedPage: currentIndex + 1)
resetImageView()
} else if (contentOffsetX == 0) {// 右滑
currentIndex = getActualCurrentPage(calculatedPage: currentIndex - 1)
resetImageView()
}
}
同時(shí),重新設(shè)置三張圖的圖片。這樣在視覺效果上,就達(dá)到了無限滾動(dòng)的效果。
fileprivate func resetImageView(){
let preIndex: NSInteger = getActualCurrentPage(calculatedPage: currentIndex - 1)
let nextIndex: NSInteger = getActualCurrentPage(calculatedPage: currentIndex + 1)
if imageUrls.count == 0 {
return
}
imageArray[0].sd_setImage(with: URL(string: imageUrls[preIndex]), placeholderImage: nil, options: [.refreshCached, .retryFailed])
imageArray[1].sd_setImage(with: URL(string: imageUrls[currentIndex]), placeholderImage: nil, options: [.refreshCached, .retryFailed])
imageArray[2].sd_setImage(with: URL(string: imageUrls[nextIndex]), placeholderImage: nil, options: [.refreshCached, .retryFailed])
scrollNode.contentOffset = CGPoint(x: self.frame.width, y: 0)// 這里不可以使用setcontentOffset:animate的方法,否則滑動(dòng)過快會出現(xiàn)bug
}
/// 根據(jù)下一頁的計(jì)算值獲取實(shí)際下一頁的值
///
/// - Parameter page: 通過+1或-1得到的下一頁的值
/// - Returns: 實(shí)際值
fileprivate func getActualCurrentPage(calculatedPage page: NSInteger) -> NSInteger {
if page == imageUrls.count {
return 0
} else if page == -1 {
return imageUrls.count - 1
} else {
return page
}
}
自定義UIPageControl
類似于優(yōu)酷的輪播圖中的UIPageControl,實(shí)現(xiàn)起來比較簡單,主要是通過改變原點(diǎn)的位置和長度,具體請參考Demo的代碼。