Swift - UIScrollView 循環(huán)滾動(dòng)

之前使用Objective-C 封裝過档泽,但是目前項(xiàng)目使用swift匆篓,對(duì)此對(duì)又封裝一個(gè)控件,便于以后應(yīng)用字支,重復(fù)寫。
功能:

  • 使用Swift4.0
  • 使用三個(gè)UIImageView實(shí)現(xiàn)無限循環(huán)
  • 支持一張或多張圖片
  • 單張不顯示pageController奸忽,不可滑動(dòng)
  • 目前使用UIImage堕伪,提供簡單版本,自己可以根據(jù)需求改動(dòng)定制栗菜,如使用SDWebImage緩存加載等

控件封裝

import UIKit
public protocol CycleScrollViewDelegate{
    func selectCycleScrollViewPage(idx:Int);
}

class CycleScrollView: JDView {
    var imageArr: Array<UIImage> = []  {
        willSet {
            self.currentPage = 0
            self.pageControl.numberOfPages = newValue.count
            self.pageControl.currentPage = 0
            if newValue.count > 1 {
                self.pageControl.isHidden = false
                self.scrollview.isScrollEnabled = true
            }
            else {
                self.pageControl.isHidden = true
                self.scrollview.isScrollEnabled = false
            }
        }
        didSet {
            self.updateImageData()
        }
    }
    var autoShow: Bool = false {
        didSet {
            if self.autoShow {
                self.startTimer()
            } else {
                self.startTimer()
            }
        }
    }
    var delegate: CycleScrollViewDelegate? = nil
    
    var currentPage: Int = 0
    
    lazy var autoTimer: Timer? = {
        let timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
        return timer
    }()
    lazy var imageVArr: Array<UIImageView> = {
        var arr: Array<UIImageView> = []
        for i in 0...2 {
            let v = UIImageView()
            arr.append(v)
        }
        return arr
    }()
    lazy var scrollview: UIScrollView = {
        let v = UIScrollView()
        v.showsVerticalScrollIndicator = false
        v.showsHorizontalScrollIndicator = false
        v.isPagingEnabled = true
        v.bounces = false
        v.delegate = self
        v.addGestureRecognizer(self.tap)
        for i in 0...2 {
            let imageV = self.imageVArr[i]
            v.addSubview(imageV)
        }
        return v
    }()
    lazy var pageControl: UIPageControl = {
        let pc = UIPageControl()
        pc.isUserInteractionEnabled = false
        pc.pageIndicatorTintColor = color_text_lightGray
        pc.currentPageIndicatorTintColor = color_nav_red
        return pc
    }()
    
    lazy var tap: UITapGestureRecognizer = {
        let tap = UITapGestureRecognizer.init(target: self, action: #selector(tapAction(_:)))
        tap.numberOfTapsRequired = 1
        tap.numberOfTouchesRequired = 1
        return tap
    }()
    
    override init() {
        super.init()
        self.addSubview(self.scrollview)
        self.addSubview(self.pageControl)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        self.scrollview.snp.makeConstraints { (make) in
            make.top.right.bottom.left.equalToSuperview()
        }
        self.pageControl.snp.makeConstraints { (make) in
            make.bottom.left.right.equalToSuperview()
            make.height.equalTo(20.0)
        }
        
        let w = self.scrollview.frame.size.width
        let h = self.scrollview.frame.size.height
        
        self.scrollview.contentSize = CGSize(width: w * 3, height: h)

        for i in 0...2 {
            let imageV = self.imageVArr[i]
            imageV.frame = CGRect(x: CGFloat(i) * w, y: 0, width: w, height: h)
        }
    }
    
    deinit {
        self.autoTimer?.invalidate()
        self.autoTimer = nil
    }
    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */

}

extension CycleScrollView {
    @objc func tapAction(_ tap: UITapGestureRecognizer) {
        if let del = self.delegate {
            del.selectCycleScrollViewPage(idx: self.currentPage)
        }
    }
    @objc func timerAction() {
        if self.currentPage == self.imageArr.count - 1{
            self.currentPage = 0
        }else{
            self.currentPage += 1
        }
        self.updateImageData()
    }
    
    func stopTimer() {
        if self.autoShow {
            self.autoTimer?.fireDate = Date.distantFuture
        }
    }
    func startTimer() {
        if self.autoShow {
            self.autoTimer?.fireDate = Date.distantPast
        }
    }
    
    func updateImageData() {
        let imageV0 = self.imageVArr[0]
        let imageV1 = self.imageVArr[1]
        let imageV2 = self.imageVArr[2]
        
        if self.imageArr.count == 1 {
            imageV0.image = self.imageArr[0]
            imageV1.image = self.imageArr[0]
            imageV2.image = self.imageArr[0]
        }
        else {
            if self.currentPage == 0 {
                imageV0.image = self.imageArr.last
                imageV1.image = self.imageArr[self.currentPage]
                imageV2.image = self.imageArr[self.currentPage + 1]
            } else if currentPage == self.imageArr.count - 1 {
                imageV0.image = self.imageArr[self.currentPage - 1]
                imageV1.image = self.imageArr[self.currentPage]
                imageV2.image = self.imageArr.first
            }
            else {
                imageV0.image = self.imageArr[self.currentPage - 1]
                imageV1.image = self.imageArr[self.currentPage]
                imageV2.image = self.imageArr[self.currentPage + 1]
            }
            self.pageControl.currentPage = currentPage
            self.scrollview.contentOffset = CGPoint(x: self.frame.size.width, y: 0)
        }
    }
    
    func endScrollMethod(_ ratio: CGFloat) {
        if ratio <= 0.7 {
            if self.currentPage - 1 < 0 {
                self.currentPage = self.imageArr.count - 1
            } else {
                self.currentPage -= 1
            }
        }
        if ratio >= 1.3 {
            if self.currentPage == self.imageArr.count - 1 {
                self.currentPage = 0
            }
            else {
                self.currentPage += 1
            }
        }
        self.updateImageData()
        self.startTimer()
    }
}
extension CycleScrollView: UIScrollViewDelegate {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let ratio = scrollView.contentOffset.x/self.frame.size.width
        self.endScrollMethod(ratio)
    }
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if !decelerate {
            let ratio = scrollView.contentOffset.x/self.frame.size.width
            self.endScrollMethod(ratio)
        }
    }
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        self.stopTimer()
    }
    
}

控件應(yīng)用

let cycleScrollView = CycleScrollView.init()
cycleScrollView.imageArr = [UIImage(named: "image01")] as! Array<UIImage>//, UIImage(named: "image02"), UIImage(named: "image03"), UIImage(named: "image04")
cell?.cycleScrollView.autoShow = true

參考文章

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末欠雌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子苛萎,更是在濱河造成了極大的恐慌桨昙,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腌歉,死亡現(xiàn)場離奇詭異蛙酪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)翘盖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門桂塞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人馍驯,你說我怎么就攤上這事阁危。” “怎么了汰瘫?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵狂打,是天一觀的道長。 經(jīng)常有香客問我混弥,道長趴乡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任蝗拿,我火速辦了婚禮晾捏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哀托。我一直安慰自己惦辛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布仓手。 她就那樣靜靜地躺著胖齐,像睡著了一般玻淑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上市怎,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天岁忘,我揣著相機(jī)與錄音,去河邊找鬼区匠。 笑死干像,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的驰弄。 我是一名探鬼主播麻汰,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼戚篙!你這毒婦竟也來了五鲫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤岔擂,失蹤者是張志新(化名)和其女友劉穎位喂,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乱灵,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡塑崖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痛倚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片规婆。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蝉稳,靈堂內(nèi)的尸體忽然破棺而出抒蚜,到底是詐尸還是另有隱情,我是刑警寧澤耘戚,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布嗡髓,位于F島的核電站,受9級(jí)特大地震影響收津,放射性物質(zhì)發(fā)生泄漏器贩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一朋截、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吧黄,春花似錦部服、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奉芦。三九已至,卻和暖如春剧蹂,著一層夾襖步出監(jiān)牢的瞬間声功,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國打工宠叼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留先巴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓冒冬,卻偏偏與公主長得像伸蚯,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子简烤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 1剂邮、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,969評(píng)論 3 119
  • 屋外白光有氣無力,天空依舊深深横侦,嘆了一口氣挥萌,口內(nèi)不覺念出“寂寞梧桐深院鎖清秋”。盡管氣候不是深秋枉侧,院里倒是有小小的...
    西窗紅燭閱讀 191評(píng)論 0 1
  • 我喜歡設(shè)計(jì)引瀑,從高中開始就覺得自己將來想做設(shè)計(jì),高考志愿填的也是清一色的設(shè)計(jì)棵逊。的確伤疙,把愛好和工作相結(jié)合是一件幸運(yùn)的事...
    imsilentfish閱讀 453評(píng)論 0 5
  • #自我管理之人際關(guān)系管理# 昨天分享的是四種性格色彩的寶寶們綜合特點(diǎn)。今天我要和大家分享辆影,各個(gè)色彩性格的人其優(yōu)勢及...
    JessicaPeng閱讀 214評(píng)論 3 2
  • 所以徒像。 我做得 還不夠 好。
    醬油來閱讀 106評(píng)論 0 0