iOS利用CollectionView+SDWebImage实现轮播图

该项目主要利用CollectionView+SDWebImage+Alamofire请求斗鱼数据实现轮播图
主要解释核心代码 比较基础的布局等就不讲解啦 可以到 我的github上运行完整的demo

两个视图控件属性
一个就是UICollectionView用于显示轮播图 需要在其中加入自定义的CollectionViewCell
一个是UIPageControl用于进行翻页显示
两个定义属性
一个定时器用于设置图片定时的切换
一个是用于网络请求完成之后进行CollectionView UI数据的刷新

//控件属性
    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet weak var pageControl: UIPageControl!
    //定义属性
    var cycleTimer : Timer?
    var cycleModels : [CycleModel]?
    {
        didSet
        {
            // 1.刷新collectionView
            collectionView.reloadData()
            // 2.设置pageControl个数
            pageControl.numberOfPages = cycleModels?.count ?? 0
            // 3.默认滚动到中间某个位置
            let indexPath = NSIndexPath(item:(cycleModels?.count ?? 0) * 10, section: 0)
            collectionView.scrollToItem(at: indexPath as IndexPath, at: .left, animated: false)
            // 4.添加定时器
            removeCycleTiemr()
            addCycleTimer()
        }
    }

CollectionView最重要的就是要显示Item
通过数据代理协议设置了Item显示的数量 但是这里的Item不是固定的数值 是从网络请求返回回来的数组大小,这里对数值*1000的原因是为了增加轮播图的隐性数量,这样用户在滑动轮播图的时候不会出现滑动5次10次就滑完了
设置cell的时候需要取余同理,就是为了利用有限的数组数据显示数值更大的IndexPath.item

// 遵守UICollectionView的数据代理协议
extension CycleCollectionView : UICollectionViewDataSource
{
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        // 设置可以横向滑动的Item数量
        return (cycleModels?.count ?? 0 ) * 1000
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CycleCellID, for: indexPath) as! CycleCollectionViewCell
        cell.cycleModel = cycleModels?[indexPath.item % (cycleModels?.count)!]
        return cell
    }
}

这里实现了CollectionView的代理协议,获取滚动的偏移量的时候+ scrollView.bounds.width * 0.5目的是用户如果滑过了本图的一半,那么图片就切换到下一张,如果不是还是恢复原型。此外在用户进行滑动的时候我们移除定时器是为了不让定时器和滑动操作起冲突,滑动的时候不应该还在切换轮播图。

// 遵守UICollectionView的代理协议
extension CycleCollectionView : UICollectionViewDelegate
{
    func scrollViewDidScroll(_ scrollView: UIScrollView)
    {
        // 1.获取滚动的偏移量
        let offsetX = scrollView.contentOffset.x + scrollView.bounds.width * 0.5
        // 2.计算pageControl的currentIndex
        pageControl.currentPage = Int(offsetX / scrollView.bounds.width) % (cycleModels?.count ?? 1)
    }
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView)
    {
        removeCycleTiemr()
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool)
    {
        addCycleTimer()
    }
}

开启轮播就是设置一个定时器然后调用滚动函数。

// 对定时器的操作方法
extension CycleCollectionView{
    private func addCycleTimer()
    {
    	// 设置定时器
        cycleTimer = Timer(timeInterval: 3.0, target: self, selector: #selector(self.scrollToNext), userInfo: nil, repeats: true)
        // 把定时器加入RunLoop中
        RunLoop.main.add(cycleTimer!, forMode: RunLoop.Mode.common)
    }
    
    private func removeCycleTiemr()
    {
        // 从运行循环中移除
        cycleTimer?.invalidate()
        cycleTimer = 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)
    }
}

这里主要是请求json数据进行解析,赋值给cell的模型。

// 请求轮播的数据
    func requestCycleData(finishCallback :@escaping () -> ())
    {
        NetworkTools.requestData(type:.GET, urlString: "http://www.douyutv.com/api/v1/slide/6", parameters: ["version" : "2.300" as AnyObject]) {
            (result) in
            //获取整体字典数据
            guard let resultDict = result as? [String : NSObject] else {return}
            
            //2.根据data的key获取数据
            guard let dataArray = resultDict["data"] as? [[String : NSObject]] else {return}
            
            //3.字典转模型对象
            
            for dict in dataArray
            {
                cycleModels.append(CycleModel(dict : dict ) )
            }
            finishCallback()
        }
    }

我们在CycCollectionViewCell中监听Model的变化,当Model变化的时候利用SDWebImage进行图片加载,思路是先在缓存中查找是否有该图片,如果没有的话就利用图片的URL进行下载并且保存。


class CycleCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var iconImageView: UIImageView!
    
    var cycleModel : CycleModel?
    {
        didSet{
            
            titleLabel.text = cycleModel?.title
            let iconURL = URL(string:(cycleModel?.pic_url)!)
        
            SDImageCache.shared.queryCacheOperation(forKey:cycleModel?.pic_url) { (image, data, cacheType) in
                if image != nil {
                    print("在缓存中找到了")
                    self.iconImageView.image = image
                }else{
                    SDWebImageManager.shared.loadImage(with: iconURL, options: [], context: [:], progress: { (min, max, url) in
                        print("加载中")
                    }) { (image, data, error, cacheType, finished, url) in
                        if (image != nil){
                            self.iconImageView.image = image
                            print("图片加载完成")
                        }else{
                            print("图片加载失败")
                        }

                    }
                }
            }
        }
    }

    
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值