实现无限轮播
生活杂谈
- 最近很多童鞋私信我,Swift项目有些语法跟不上。希望我出OC版的(OC版我会在后续推出),但是以我的考虑来说,Swift在语言排行版上面其实已经超过OC,另外国内现在新项目一般都会用Swift开发了。所有其实不能总是对于Swift是一种拒绝的态度,待在舒适区是会被淘汰的噢
- 但是对于刚从OC转Swift的人来说,确实Swift语法和OC差异太大,又没有比较好的教程。后续我会看看能不能出一个OC快速转向Swift的教程,不需要的童鞋可以先研究我们的项目,需要的童鞋可以抓紧时间学习一下
实现效果
- 轮播效果

思路分析
- 实现无限轮播常用的方案有三个:
- 第三方框架:(不推荐,该功能并不难,而且三方框架中会有很多冗余代码)
- UIScrollView:上面放三个View,自己实现三个View的循环利用
- UICollectionView:利用系统会对UICollectionViewCell的循环利用机制实现
- 方案选择:
- 方案三:简单好用,循环利用的问题交给系统自己处理即可
界面搭建
- 自定义一个UIView
- 由于该View上面内容比较固定,因此可以直接通过Xib进行描述
- 添加UICollectionView,占据整个View,右下角添加UIPageControl

- 设置UICollectionView的布局,设置数据源以及实现数据源方法(见代码)
- 切记:设置自定义View的autoresizingMask = .None,否则控件将不能显示
- 部分代码解释

// MARK:- 定义RecommendCycleView类class RecommendCycleView: UIView {// MARK: 控件属性@IBOutlet weak var collectionView: UICollectionView!@IBOutlet weak var pageControl: UIPageControl!// MARK: 系统回调override func awakeFromNib() {super.awakeFromNib()// 设置不自动拉伸autoresizingMask = .None// 注册cellcollectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: kCycleCellID)}override func layoutSubviews() {super.layoutSubviews()// 设置collectionView的布局let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayoutlayout.itemSize = collectionView.bounds.size}}// MARK:- 通过Xib快速创建的类方法extension RecommendCycleView {class func recommendCycleView() -> RecommendCycleView {return NSBundle.mainBundle().loadNibNamed("RecommendCycleView", owner: nil, options: nil).first as! RecommendCycleView}}// MARK:- 实现UICollectionView的数据源&代理extension RecommendCycleView : UICollectionViewDataSource {func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {return 6}func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {let cell = collectionView.dequeueReusableCellWithReuseIdentifier(kCycleCellID, forIndexPath: indexPath)cell.backgroundColor = indexPath.item % 2 == 0 ? UIColor.redColor() : UIColor.blueColor()return cell}}extension RecommendCycleView : UICollectionViewDelegate {}
-
将自定义View添加到UICollectionView中
- 懒加载RecommendCycleView对象
- 将cycleView添加到UICollectionView中
- 设置UICollectionView的内边距
- 代码如下:
-
懒加载RecommendCycleView
private lazy var cycleView : RecommendCycleView = {let cycleView = RecommendCycleView.recommendCycleView()cycleView.frame = CGRect(x: 0, y: -kCycleViewH, width: kScreenW, height: kCycleViewH)return cycleView}()
- 添加到collectionView中
// 添加cycleViewcollectionView.addSubview(cycleView)collectionView.contentInset = UIEdgeInsets(top: kCycleViewH, left: 0, bottom: 0, right: 0)
请求数据&展示数据
请求数据
- 接口描述
- 接口名称:顶部轮播数据
- 接口地址:http://www.douyutv.com/api/v1/slide/6
- 请求参数:</br>
| 参数名称 | 参数说明 |
|---|---|
| version | 当前版本号:2.300 |
- 在RecommendViewMode中发送网络请求
- 根据接口发送请求
- 定义CycleModel模型
- 将请求到的数据转成模型对象
- 模型定义
class CycleModel: NSObject {/// 轮播标题var title : String = ""/// 轮播图片var pic_url : String = ""/// 轮播对应主播信息var anchor : AnchorModel?/// 主播信息var room : [String : NSObject]? {didSet {guard let room = room else { return }anchor = AnchorModel(dict: room)}}// MARK: 构造函数init(dict : [String : NSObject]) {super.init()setValuesForKeysWithDictionary(dict)}override func setValue(value: AnyObject?, forUndefinedKey key: String) {}}
- 数据请求
func requestCycleData(finishedCallback : () -> ()) {NetworkTools.requestData(.GET, URLString: "http://www.douyutv.com/api/v1/slide/6?version=2.300") { (result) in// 1.将结果转成字典guard let resultDict = result as? [String : NSObject] else { return }guard let dataArray = resultDict["data"] as? [[String : NSObject]] else { return }// 2.将字典转成模型对象for dict in dataArray {self.cycleModels.append(CycleModel(dict: dict))}finishedCallback()}}
展示数据
- 将数据传递给RecommendCycleView对象
- 刷新UICollectionView
- 设置UIPageControl的个数
- 自定义Cell,用于展示数据
- 通过xib直接描述Cell

- 通过xib直接描述Cell
- 根据模型展示数据
- 代码如下:
class CollectionCycleCell: UICollectionViewCell {// MARK: 控件属性@IBOutlet weak var iconImageView: UIImageView!@IBOutlet weak var titleLabel: UILabel!// MARK: 定义模型属性var cycleModel : CycleModel? {didSet {titleLabel.text = cycleModel?.titlelet iconURL = NSURL(string: cycleModel?.pic_url ?? "")!iconImageView.kf_setImageWithURL(iconURL)}}}
实现无限轮播功能
- 在返回Cell个数地方,返回无限个数
- 例如:(cycleModels?.count ?? 0) * 10000
- 原因:无论用户怎么滚动,滚动几天可能才能滚完
- 另外:因为Cell有循环利用,是不会常见那么多Cell的。不会造成内存很大
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {return (cycleModels?.count ?? 0) * 10000}
- 随着用户的滚动,改变pageControl的显示
- 监听UICollectionView的滚动即可
func scrollViewDidScroll(scrollView: UIScrollView) {let offset = scrollView.contentOffset.x + scrollView.bounds.width * 0.5pageControl.currentPage = Int(offset / scrollView.bounds.width) % (cycleModels?.count ?? 1)}
-
让用户向前滚动也可以
- 默认滚动到60处,那么用户向前滚动也有内容
- 注意:不需要太多,因为用户习惯来讲是很少向前滚动的
let indexPath = NSIndexPath(forItem: (cycleModels?.count ?? 0) * 10, inSection: 0)collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .Left, animated: false)
-
自动滚动功能
- 添加定时器
- 每隔3秒钟自动滚动到下一个
// MARK:- 对定时器操作方法extension RecommendCycleView {private func addCycleTimer() {cycleTimer = NSTimer(timeInterval: 3, target: self, selector: #selector(self.scrollToNext), userInfo: nil, repeats: true)NSRunLoop.mainRunLoop().addTimer(cycleTimer!, forMode: NSRunLoopCommonModes)}private func removeCycleTimer() {cycleTimer?.invalidate()cycleTimer = nil}@objc private func scrollToNext() {// 滚动collectionViewlet currentOffSet = collectionView.contentOffset.x + collectionView.bounds.widthcollectionView.setContentOffset(CGPoint(x: currentOffSet, y: 0), animated: true)}}
- 监听用户拖拽
- 用户拖拽过程中,定时器不更新
- 监听用户拖拽&结束拖拽即可
func scrollViewWillBeginDragging(scrollView: UIScrollView) {removeCycleTimer()}func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {addCycleTimer()}
本文介绍了一种使用UICollectionView实现无限轮播效果的方法,并详细解释了如何通过代码配置UICollectionView及其实现无限滚动的关键技巧。
1万+

被折叠的 条评论
为什么被折叠?



