該項目主要利用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
}
}