最近学习到一种快速创建轮播器的方法,感觉比以前自己实现的都要简单,记录下
1.实现思路:
UI:
CycleView.xib使用CollcetionView来做循环滚动也没有任何的性能问题!
1.创建一个CycleView,CycleView由一个CollectionView(与CycleView一样大)和pageCotrol两个控件组成。
2.自定义CollectionViewCell,每个Cell大小等于CycleView的大小
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var pageControl: UIPageControl!
var titles: [String]? //数据数组,暂时放的字符串
var timer: Timer? //定时器
调整尺寸
override func layoutSubviews() {
super.layoutSubviews()
//获取layout属性
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = collectionView.bounds.size
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.scrollDirection = .horizontal
collectionView.isPagingEnabled = true
}
2.循环滚动思路:
2.1 CollectionView的逻辑
1.numberOfItemsInSection 方法中,将titles的个数*500,如果500嫌少,可以乘以1000。
extension CycelView: UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (titles?.count ?? 0)*500
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//获取当前的cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kCellID, for: indexPath) as! CycleCell
//由于在numberOfItemsInSection方法中*500,所以通过对titles.count取余获得对应的index,展示对应的数据
let index = indexPath.item % titles!.count
cell.num = titles?[index]
cell.backgroundColor = UIColor.randomColor()
return cell
}
}
2.2 PageControl的逻辑
pageControl的逻辑主要就是在滚动的时候随着页面变化而变化。
extension CycelView: UICollectionViewDelegate{
func scrollViewDidScroll(_ scrollView: UIScrollView) {
//获取滚动的偏移量
let offsetx = scrollView.contentOffset.x
//2.计算pageControl的currentindex
pageControl.currentPage = Int(offsetx / scrollView.bounds.width + 0.5) % (titles?.count ?? 1)
}
}
2.3 定时器逻辑
主要是在创建的时候添加定时器,在开始滚动的时候移除定时器。停止移动的时候添加定时器
extension CycelView{
///创建定时器的方法
fileprivate func addCycleTimer(){
timer = Timer(timeInterval: 2.0, target: self, selector: #selector(scrollToNext), userInfo: nil, repeats: true)
RunLoop.main.add(timer!, forMode: .commonModes)
}
//移除定时器
fileprivate func removeTimer(){
timer?.invalidate() //从运行循环中移除
timer = nil
}
@objc private func scrollToNext(){
//1.获取当前的滚动
let currentOffsetX = collectionView.contentOffset.x
let offsetX = currentOffsetX + collectionView.bounds.width
//2.滚动到该位置
collectionView.setContentOffset(CGPoint(x:offsetX,y:0), animated: true)
}
}
在UICollectionViewDelegate的代理方法中,还要进行移除和添加定时器
extension CycelView: UICollectionViewDelegate{
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
removeTimer()
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool){
addCycleTimer()
}
}
2.4 循环滚动逻辑梳理
在ViewController中创建完成了CycleView,将数据数组传入
fileprivate lazy var cycleView: CycelView = {
let cycleView = CycelView.cycleView()
cycleView.frame = CGRect(x: 0, y: 20, width: kScreenW, height: kCycleViewH)
return cycleView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(cycleView);
cycleView.titles = ["0","1","2","3","4","5","6"]
}
在CycleView中titels接收到数据后在didSet里面进行处理
var titles: [String]?{
didSet{
//1.刷新布局
collectionView.reloadData()
//2.设置pagecontrol个数
pageControl.numberOfPages = titles?.count ?? 0
//3.默认滚动到中间某一个位置
let indexPath = IndexPath(item: (titles?.count ?? 0) * 10, section: 0)
collectionView.scrollToItem(at: indexPath, at: .left, animated: false)
//4.添加定时器
removeTimer() //为了安全起见,先移除定时器,再添加定时器
addCycleTimer()
}
}
CycleViewDemo链接: https://github.com/WzhGoSky/Demo
网友评论