该项目主要利用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
}
}