玩转【斗鱼直播APP】系列之实现无限轮播

实现无限轮播

生活杂谈

  • 最近很多童鞋私信我,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,否则控件将不能显示
    • 部分代码解释
 
 
  1. // MARK:- 定义RecommendCycleView类
  2. class RecommendCycleView: UIView {
  3. // MARK: 控件属性
  4. @IBOutlet weak var collectionView: UICollectionView!
  5. @IBOutlet weak var pageControl: UIPageControl!
  6. // MARK: 系统回调
  7. override func awakeFromNib() {
  8. super.awakeFromNib()
  9. // 设置不自动拉伸
  10. autoresizingMask = .None
  11. // 注册cell
  12. collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: kCycleCellID)
  13. }
  14. override func layoutSubviews() {
  15. super.layoutSubviews()
  16. // 设置collectionView的布局
  17. let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
  18. layout.itemSize = collectionView.bounds.size
  19. }
  20. }
  21. // MARK:- 通过Xib快速创建的类方法
  22. extension RecommendCycleView {
  23. class func recommendCycleView() -> RecommendCycleView {
  24. return NSBundle.mainBundle().loadNibNamed("RecommendCycleView", owner: nil, options: nil).first as! RecommendCycleView
  25. }
  26. }
  27. // MARK:- 实现UICollectionView的数据源&代理
  28. extension RecommendCycleView : UICollectionViewDataSource {
  29. func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  30. return 6
  31. }
  32. func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
  33. let cell = collectionView.dequeueReusableCellWithReuseIdentifier(kCycleCellID, forIndexPath: indexPath)
  34. cell.backgroundColor = indexPath.item % 2 == 0 ? UIColor.redColor() : UIColor.blueColor()
  35. return cell
  36. }
  37. }
  38. extension RecommendCycleView : UICollectionViewDelegate {
  39. }
  • 将自定义View添加到UICollectionView中

    • 懒加载RecommendCycleView对象
    • 将cycleView添加到UICollectionView中
    • 设置UICollectionView的内边距
    • 代码如下:
  • 懒加载RecommendCycleView

 
 
  1. private lazy var cycleView : RecommendCycleView = {
  2. let cycleView = RecommendCycleView.recommendCycleView()
  3. cycleView.frame = CGRect(x: 0, y: -kCycleViewH, width: kScreenW, height: kCycleViewH)
  4. return cycleView
  5. }()
  • 添加到collectionView中
 
 
  1. // 添加cycleView
  2. collectionView.addSubview(cycleView)
  3. collectionView.contentInset = UIEdgeInsets(top: kCycleViewH, left: 0, bottom: 0, right: 0)

请求数据&展示数据

请求数据
参数名称参数说明
version当前版本号:2.300
  • 在RecommendViewMode中发送网络请求
    • 根据接口发送请求
    • 定义CycleModel模型
    • 将请求到的数据转成模型对象
  • 模型定义
 
 
  1. class CycleModel: NSObject {
  2. /// 轮播标题
  3. var title : String = ""
  4. /// 轮播图片
  5. var pic_url : String = ""
  6. /// 轮播对应主播信息
  7. var anchor : AnchorModel?
  8. /// 主播信息
  9. var room : [String : NSObject]? {
  10. didSet {
  11. guard let room = room else { return }
  12. anchor = AnchorModel(dict: room)
  13. }
  14. }
  15. // MARK: 构造函数
  16. init(dict : [String : NSObject]) {
  17. super.init()
  18. setValuesForKeysWithDictionary(dict)
  19. }
  20. override func setValue(value: AnyObject?, forUndefinedKey key: String) {}
  21. }
  • 数据请求
 
 
  1. func requestCycleData(finishedCallback : () -> ()) {
  2. NetworkTools.requestData(.GET, URLString: "http://www.douyutv.com/api/v1/slide/6?version=2.300") { (result) in
  3. // 1.将结果转成字典
  4. guard let resultDict = result as? [String : NSObject] else { return }
  5. guard let dataArray = resultDict["data"] as? [[String : NSObject]] else { return }
  6. // 2.将字典转成模型对象
  7. for dict in dataArray {
  8. self.cycleModels.append(CycleModel(dict: dict))
  9. }
  10. finishedCallback()
  11. }
  12. }
展示数据
  • 将数据传递给RecommendCycleView对象
    • 刷新UICollectionView
    • 设置UIPageControl的个数
  • 自定义Cell,用于展示数据
    • 通过xib直接描述Cell
  • 根据模型展示数据
    • 代码如下:
 
 
  1. class CollectionCycleCell: UICollectionViewCell {
  2. // MARK: 控件属性
  3. @IBOutlet weak var iconImageView: UIImageView!
  4. @IBOutlet weak var titleLabel: UILabel!
  5. // MARK: 定义模型属性
  6. var cycleModel : CycleModel? {
  7. didSet {
  8. titleLabel.text = cycleModel?.title
  9. let iconURL = NSURL(string: cycleModel?.pic_url ?? "")!
  10. iconImageView.kf_setImageWithURL(iconURL)
  11. }
  12. }
  13. }

实现无限轮播功能

  • 在返回Cell个数地方,返回无限个数
    • 例如:(cycleModels?.count ?? 0) * 10000
    • 原因:无论用户怎么滚动,滚动几天可能才能滚完
    • 另外:因为Cell有循环利用,是不会常见那么多Cell的。不会造成内存很大
 
 
  1. func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  2. return (cycleModels?.count ?? 0) * 10000
  3. }
  • 随着用户的滚动,改变pageControl的显示
    • 监听UICollectionView的滚动即可
 
 
  1. func scrollViewDidScroll(scrollView: UIScrollView) {
  2. let offset = scrollView.contentOffset.x + scrollView.bounds.width * 0.5
  3. pageControl.currentPage = Int(offset / scrollView.bounds.width) % (cycleModels?.count ?? 1)
  4. }
  • 让用户向前滚动也可以

    • 默认滚动到60处,那么用户向前滚动也有内容
    • 注意:不需要太多,因为用户习惯来讲是很少向前滚动的
           
           
      1. let indexPath = NSIndexPath(forItem: (cycleModels?.count ?? 0) * 10, inSection: 0)
      2. collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .Left, animated: false)
  • 自动滚动功能

    • 添加定时器
    • 每隔3秒钟自动滚动到下一个
 
 
  1. // MARK:- 对定时器操作方法
  2. extension RecommendCycleView {
  3. private func addCycleTimer() {
  4. cycleTimer = NSTimer(timeInterval: 3, target: self, selector: #selector(self.scrollToNext), userInfo: nil, repeats: true)
  5. NSRunLoop.mainRunLoop().addTimer(cycleTimer!, forMode: NSRunLoopCommonModes)
  6. }
  7. private func removeCycleTimer() {
  8. cycleTimer?.invalidate()
  9. cycleTimer = nil
  10. }
  11. @objc private func scrollToNext() {
  12. // 滚动collectionView
  13. let currentOffSet = collectionView.contentOffset.x + collectionView.bounds.width
  14. collectionView.setContentOffset(CGPoint(x: currentOffSet, y: 0), animated: true)
  15. }
  16. }
  • 监听用户拖拽
    • 用户拖拽过程中,定时器不更新
    • 监听用户拖拽&结束拖拽即可
 
 
  1. func scrollViewWillBeginDragging(scrollView: UIScrollView) {
  2. removeCycleTimer()
  3. }
  4. func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
  5. addCycleTimer()
  6. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值