iOS swift跑馬燈滾動可以點選
阿新 • • 發佈:2018-11-22
跑馬燈,從右至左迴圈滾動顯示資訊,並且支援點選事件,使用swift4.0語法完成,更加簡介,通用性強,佈局部分全部使用snpkit
程式碼:
// // HXQMarqueeView.swift // hxquan-swift // // Created by Tiny on 2018/11/20. // Copyright © 2018年 hxq. All rights reserved. // 跑馬燈 import UIKit class MarqueeModel: Equatable{ var title: String? //內容 var img: String? //頭像圖片 url var textColor: UIColor = .black //字型預設顏色 var font: UIFont = .systemFont(ofSize: 14) //字型大小 var imageHolder: UIImage = HXQDefaultUserImage //頭像預設圖片 static func == (lhs: MarqueeModel, rhs: MarqueeModel) -> Bool { return lhs.title == rhs.title && lhs.img == rhs.img && lhs.textColor == rhs.textColor && lhs.font == rhs.font && lhs.imageHolder == rhs.imageHolder } } class MarqueeItem: UIView { private var textLb: UILabel! //文字label private var imgView: UIImageView! //圖片 /// 重寫setModel並賦值 fileprivate var model: MarqueeModel?{ didSet{ if model != nil { textLb.text = model?.title textLb.textColor = model!.textColor textLb.font = model!.font imgView.sd_setImage(with: URL(string: model!.img ?? ""), placeholderImage: model!.imageHolder) } } } override init(frame: CGRect) { super.init(frame: frame) setupUI() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } private func setupUI(){ let gesture = UITapGestureRecognizer(target: self, action: #selector(itemClick)) addGestureRecognizer(gesture) textLb = UILabel() textLb.font = UIFont.systemFont(ofSize: 14) textLb.textColor = UIColor.black addSubview(textLb) imgView = UIImageView() imgView.layer.masksToBounds = true addSubview(imgView) imgView.snp.makeConstraints { (make) in make.left.equalTo(5) make.top.equalTo(5) make.bottom.equalTo(-5) make.width.equalTo(imgView.snp.height) } textLb.snp.makeConstraints { (make) in make.centerY.equalToSuperview() make.left.equalTo(imgView.snp.right).offset(5) make.right.equalTo(-5) } } /// item被點選事件回撥 fileprivate var itemDidTap:(() -> Void)? @objc private func itemClick(){ //將事件傳遞出去 itemDidTap?() } override func layoutSubviews() { super.layoutSubviews() imgView.layer.cornerRadius = imgView.bounds.size.width*0.5 } } class HXQMarqueeView: UIView { /// 初始化scrollView private lazy var scrollView: UIScrollView = { let scrollView = UIScrollView(frame: .zero) scrollView.scrollsToTop = false scrollView.showsVerticalScrollIndicator = false scrollView.showsHorizontalScrollIndicator = false return scrollView }() /// 初始化定時器 private lazy var timer: Timer = {[unowned self] in let timer = Timer(timeInterval: 0.008, target: self, selector: #selector(startToMove), userInfo: nil, repeats: true) RunLoop.current.add(timer, forMode: .common) return timer }() override init(frame: CGRect) { super.init(frame: frame) setupUI() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } private func setupUI(){ layer.masksToBounds = true addSubview(scrollView) scrollView.snp.makeConstraints { (make) in make.top.left.bottom.equalToSuperview() make.width.equalToSuperview() } } var marqueeHolder: String? var marqueeFontSize: CGFloat = 14 var marqueeTextColor = UIColor.black public var items = [MarqueeModel](){ didSet{ //判斷2次資料是否相同 if oldValue == items { return } //關閉定時器 if timer.isValid { timer.fireDate = Date.distantFuture } //移除scrollView中所有控制元件 for v in scrollView.subviews{ v.removeFromSuperview() } //顯示預設 if items.isEmpty{ //如果需要顯示預設值的話 if marqueeHolder != nil{ let lb = UILabel() lb.textAlignment = .center lb.text = marqueeHolder lb.font = UIFont.systemFont(ofSize: marqueeFontSize) lb.textColor = marqueeTextColor scrollView.addSubview(lb) lb.snp.makeConstraints { (make) in make.height.equalToSuperview() make.left.equalTo(20) } //更新scrollView的ContentSize scrollView.snp.makeConstraints { (make) in make.right.equalTo(lb.snp.right) } layoutIfNeeded() scrollView.x = 0; } }else{ let margin: CGFloat = 10 let gap: CGFloat = 20 var last: MarqueeItem? for (i,model) in items.enumerated(){ let item = MarqueeItem() item.model = model item.itemDidTap = { [unowned self] in self.selectionBlock?(model,i) } scrollView.addSubview(item) item.snp.makeConstraints { (make) in if last == nil{ make.left.equalTo(margin) }else{ make.left.equalTo(last!.snp.right).offset(gap) } make.height.equalToSuperview() } last = item } //更新scrollView的ContentSize scrollView.snp.makeConstraints { (make) in make.right.equalTo(last!.snp.right).offset(margin) } layoutIfNeeded() //拿到contentSize重新更新scrollView約束 scrollView.snp.remakeConstraints { (make) in make.width.equalTo(scrollView.contentSize.width) make.top.bottom.equalToSuperview() make.right.equalTo(last!.snp.right).offset(margin) make.left.equalTo(self.snp.right) } //開始啟動定時器 timer.fireDate = Date(timeIntervalSinceNow: 0) } } } private var selectionBlock: ((MarqueeModel,Int) -> Void)? public func queeSelection(_ callBack: ((MarqueeModel,Int) -> Void)?){ selectionBlock = callBack } @objc private func startToMove(){ scrollView.x = scrollView.x - 0.5 ; if scrollView.x <= -scrollView.contentSize.width { scrollView.x = self.bounds.size.width; } } deinit { if timer.isValid { timer.invalidate() } } }
使用方法:
//建立 let marquee = HXQMarqueeView() view.addSubview(marquee) //設定約束 marquee.snp.makeConstraints { (make) in make.left.equalTo(20) make.right.equalTo(-20) make.top.equalTo(100) make.height.equalTo(30) } //初始化資料來源 var array = [MarqueeModel]() for i in 0..<5 { let item = MarqueeModel() item.title = "我完事了,你們呢\(i)" item.img = "" item.textColor = UIColor.black item.font = UIFont.systemFont(ofSize: 14) array.append(item) } //賦值 marquee.items = array //監聽點選 marquee.queeSelection { (model, index) in print("\(model.title ?? "") + \(index)") }