之前使用Objective-C 封装过,但是目前项目使用swift,对此对又封装一个控件,便于以后应用,重复写。
功能:
- 使用Swift4.0
- 使用三个UIImageView实现无限循环
- 支持一张或多张图片
- 单张不显示pageController,不可滑动
- 目前使用UIImage,提供简单版本,自己可以根据需求改动定制,如使用SDWebImage缓存加载等
控件封装
import UIKit
public protocol CycleScrollViewDelegate{
func selectCycleScrollViewPage(idx:Int);
}
class CycleScrollView: JDView {
var imageArr: Array = [] {
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 = {
var arr: Array = []
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()
}
}
控件应用
let cycleScrollView = CycleScrollView.init()
cycleScrollView.imageArr = [UIImage(named: "image01")] as! Array//, UIImage(named: "image02"), UIImage(named: "image03"), UIImage(named: "image04")
cell?.cycleScrollView.autoShow = true
参考文章