教你寫個(gè)圖片輪播

圖片輪播.gif

這是一個(gè)圖片輪播的 Demo,上半部分用 CollectionView 實(shí)現(xiàn),沒有無限循環(huán)效果,下半部分是用 ScrollView 實(shí)現(xiàn)的,自動(dòng)無限輪播。代碼地址在這里。

上次用 CollectionView 實(shí)現(xiàn)了一個(gè)多表視圖,這次本來想用同樣的思路實(shí)現(xiàn)個(gè)圖片輪播,結(jié)果發(fā)現(xiàn)并不是很方便。主要是“無限循環(huán)滑動(dòng)”的效果單純用 CollectionView 的接口的話基本做不到,要做也只能是把待顯示圖片的數(shù)量 * N(N是一個(gè)很大的數(shù)),可以做到在比較長的時(shí)間內(nèi)一直向后輪播,因?yàn)?Cell 的復(fù)用機(jī)制,真正使用的只有兩個(gè) Cell 對象,所以不用擔(dān)心內(nèi)存爆炸。但是這樣做不到手勢滑動(dòng)的“首尾連接”,就是無論往左還是往右都可以無限滑動(dòng),要達(dá)到這樣的效果,還是得用到 ScrollView 的接口,所以我覺得還不如直接用 ScrollView 寫好了。

用 ScrollView 實(shí)現(xiàn)“首尾連接”有一種常見的思路:

frame_content.png

白色邊框代表 ScrollView 的 frame,藍(lán)色部分是 content。簡單來說就是在要顯示的圖片的左右兩邊各加一張圖片作為橋接。譬如當(dāng)前顯示的是第一張圖片(img1),按理說再用手往右滑動(dòng)的話啥都沒有了,但現(xiàn)在我在img1的左邊又加了一張img3,這樣在向右滑動(dòng)的時(shí)候我們還能看到 img3,然后在滑動(dòng)即將停下的時(shí)候,快速切換到第四個(gè)位置的 img3,所以最左邊的 img3 永遠(yuǎn)不會(huì)在靜止的時(shí)候顯示?,F(xiàn)在如果再向右滑動(dòng)的話,就正?;?img2。向左滑動(dòng)的時(shí)候同理,在滑到最后的那張 img1的一瞬間,切換到第二個(gè)位置的 img1。代碼如下:

extension AutoScrollView: UIScrollViewDelegate {
    //速度變慢,即將停下的時(shí)候調(diào)用
    func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
        //因?yàn)榭梢宰笥一?,所以不能簡單地?,而要通過contentofff計(jì)算要滑到第幾張圖片
        let page = Int(scrollView.contentOffset.x / width)
        if page == 0 {
            scrollView.contentOffset.x = width * CGFloat(imageCount)
        } else if page == imageCount + 1 {
            scrollView.contentOffset.x = width
        }
        
        pageCtrl.currentPage = Int(scrollView.contentOffset.x / width) - 1  
    }
}

上面說的主要是對手勢滑動(dòng)部分的處理,至于按固定時(shí)間間隔向右輪播更簡單。只要判斷一下當(dāng)前顯示的是否是最后一張圖片(img3),如果是,那下一張就顯示第一張(img1),否則正常顯示下一張圖片:

func slideByTime() {
    var page = pageCtrl.currentPage + 1
    
    if page == imageCount {
        scrollView.contentOffset.x = width
        page = 0
    } else {
        self.scrollView.contentOffset.x = self.width * CGFloat(page + 1)
    }
    
    pageCtrl.currentPage = page
}

然后用一個(gè)計(jì)時(shí)器定時(shí)調(diào)用上面這個(gè)方法就好了。有的同學(xué)可能會(huì)直接調(diào)用NSTimerscheduledTimerWithTimeInterval方法,但是這個(gè)方法有個(gè)潛在的危險(xiǎn),一旦將target參數(shù)設(shè)為self,repeat參數(shù)設(shè)為true,NSTimer就會(huì)獲取當(dāng)前對象的一個(gè)引用,而且極難打破這個(gè)引用,這樣當(dāng)前對象就不能被正確釋放,極易造成內(nèi)存泄漏。

解決方法是把要執(zhí)行的方法作為一個(gè) block 傳給 NSTimeruserInfo屬性,把target參數(shù)設(shè)為NSTimer自己,給NSTimer增加一個(gè)擴(kuò)展方法sy_procInvoke,在方法體中執(zhí)行userInfo

typealias Proc = @convention(block) () -> ()
extension NSTimer {
    class func sy_scheduledTimeerWithTimeInterval(interval: NSTimeInterval, repeats: Bool, repeatHandler: Proc) {
        scheduledTimerWithTimeInterval(interval, target: self, selector: "sy_procInvoke:", userInfo: unsafeBitCast(repeatHandler, AnyObject.self), repeats: true)
    }
    
    class func sy_procInvoke(timer: NSTimer) {
        let proc = unsafeBitCast(timer.userInfo, Proc.self)
        proc()
    }
}

因?yàn)?code>userInfo的類型是個(gè) AnyObject,而 Swift 中的閉包是不能轉(zhuǎn)化為AnyObject的,所以得定義一個(gè)block類型,就是這一句typealias Proc = @convention(block) () -> (),然后在傳給userInfo的時(shí)候轉(zhuǎn)化為AnyObject類型。

調(diào)用的時(shí)候用weak修飾self

//計(jì)時(shí)器
NSTimer.sy_scheduledTimeerWithTimeInterval(1, repeats: true) { [weak self] in
    self?.slideByTime()
}

這樣每隔1秒就會(huì)執(zhí)行slideByTime方法,而且NSTimer沒有持有當(dāng)前對象的引用,任務(wù)完成。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 關(guān)于輪播圖的實(shí)現(xiàn), zz所了解到的有三種: 利用scrollView根據(jù)輪播圖片的多少來創(chuàng)建imageview 然...
    zz__我不二閱讀 3,212評論 2 13
  • 實(shí)現(xiàn)思路 依然是用到UIScrollView,不同的是這次運(yùn)用重用的思想,因?yàn)椴还芪覀冇卸嗌購垐D片要輪播,在UIS...
    Salad可樂閱讀 2,616評論 11 1
  • 1、《活出生命的意義》--作者 弗蘭克爾 前四章精彩句子 大概也就是在我4歲那年,有一天晚上快入睡時(shí),我突然被腦海...
    Pheeb閱讀 181評論 0 0
  • XX在幾百年前說過:學(xué)以致用,方為學(xué)習(xí)的目的。 那作為學(xué)習(xí)者,我們問問自己: 怎樣的學(xué)習(xí)效果,才是做到學(xué)以致用? ...
    親愛的悅?cè)?/span>閱讀 979評論 5 4
  • 此時(shí)我一個(gè)人早早的來到教室,坐我一直以來都坐的位置。我一旦認(rèn)準(zhǔn)了位置就不會(huì)輕易改變。 大一上學(xué)期,每次都早早的去教...
    頭發(fā)濃密小寶貝閱讀 345評論 6 3

友情鏈接更多精彩內(nèi)容