今天開始仿寫半糖APP,首頁頂部有一個無限輪播的Scroll View。
這個可以用第三方庫SDCycleScrollView來實現(xiàn),很方便,這里我嘗試自己實現(xiàn)。
實現(xiàn)原理采用collection view,將圖片*100作為collection view 的data source,然后自動翻頁播放,目前可以實現(xiàn)自動播放,本想添加弧形蒙版,可是考慮到貝塞爾曲線一些參數(shù)不清楚,加出來的很丑,所以暫時不添加。
代碼如下:
import UIKit
class CycleScrollView: UIView {
private let reusableCycleCell = "CycleCell"
//圖片
private var imageGroup:[UIImage]?
private var imageURLStrings:[String]?
private var pageIndicator:UIPageControl?
private var bezierPath:UIBezierPath?
private var timer:NSTimer?
private var collectionView:UICollectionView?
private var collectionViewFlowLayout:UICollectionViewFlowLayout?
private var pageCount:Int = 1
private var scrollInterval:Double = 3.0
private var counter:Int = 0
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
convenience init(frame:CGRect, imageGroup:[UIImage]) {
self.init(frame:frame)
self.imageGroup = imageGroup
self.pageCount = imageGroup.count
setUpScrollView()
addPageIndicator()
setUpAutoScrollTimer()
}
convenience init(frame:CGRect, imageURLStrings:[String]) {
self.init(frame:frame)
self.imageURLStrings = imageURLStrings
self.pageCount = imageURLStrings.count
self.imageGroup = imageURLStrings.map({(urlString) -> UIImage in
if let data = NSData(contentsOfURL: NSURL(string: urlString)!) {
if let image = UIImage(data: data) {
return image
} else {
return UIImage(named: "scrollImage_1")!
}
} else {
return UIImage(named: "scrollImage_2")!
}
})
setUpScrollView()
addPageIndicator()
setUpAutoScrollTimer()
}
//設置scroll view
internal func setUpScrollView(){
//collection view flow lay out
collectionViewFlowLayout = UICollectionViewFlowLayout()
collectionViewFlowLayout!.minimumInteritemSpacing = 0
collectionViewFlowLayout!.minimumLineSpacing = 0
collectionViewFlowLayout!.scrollDirection = UICollectionViewScrollDirection.Horizontal
collectionView = UICollectionView(frame: self.frame, collectionViewLayout: collectionViewFlowLayout!)
collectionView?.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reusableCycleCell)
collectionView?.pagingEnabled = true
collectionView?.showsHorizontalScrollIndicator = false
collectionView?.showsVerticalScrollIndicator = false
collectionView?.dataSource = self
collectionView?.delegate = self
self.addSubview(collectionView!)
}
//添加頁面指示
internal func addPageIndicator(){
pageIndicator = UIPageControl()
pageIndicator?.numberOfPages = pageCount
pageIndicator?.hidesForSinglePage = true
pageIndicator?.currentPageIndicatorTintColor = UIColor.redColor()
pageIndicator?.pageIndicatorTintColor = UIColor.lightGrayColor()
pageIndicator?.frame.size = (pageIndicator?.sizeForNumberOfPages(pageCount))!
pageIndicator?.center = CGPointMake(self.centerX(),self.maxY()-8)
self.addSubview(pageIndicator!)
}
//設置自動翻頁
internal func setUpAutoScrollTimer(){
timer = NSTimer(timeInterval: scrollInterval, target: self, selector: "autoScroll", userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(timer!, forMode: NSRunLoopCommonModes)
}
internal func autoScroll(){
counter++
self.collectionView?.scrollToItemAtIndexPath(NSIndexPath(forItem: counter, inSection: 0), atScrollPosition: UICollectionViewScrollPosition.None, animated: true)
}
//添加蒙版圖層
internal func addMaskLayer(){
bezierPath = UIBezierPath(ovalInRect: CGRectMake(0, self.maxY() - 30, self.width(), 60))
let maskLayer = CAShapeLayer()
maskLayer.path = bezierPath!.CGPath
maskLayer.fillColor = UIColor.whiteColor().CGColor
self.layer.addSublayer(maskLayer)
}
//由于auto layout,需要在super view 尺寸計算完成之后重新計算subview的尺寸
override func layoutSubviews() {
super.layoutSubviews()
print("lay out subviews")
collectionViewFlowLayout?.itemSize = self.frame.size
collectionView?.frame = self.frame
pageIndicator?.center = CGPointMake(self.centerX(),self.maxY()-8)
}
}
//MARK:Collection View Data Source
extension CycleScrollView:UICollectionViewDataSource {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return pageCount * 100
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reusableCycleCell, forIndexPath: indexPath)
let imageView = UIImageView(frame: cell.contentView.frame)
imageView.image = imageGroup![indexPath.row % pageCount]
cell.contentView.addSubview(imageView)
return cell
}
}
//MARK:Scroll View Delegate,此處完成設置手動翻頁與自動翻頁之間的切換
extension CycleScrollView:UIScrollViewDelegate {
//當翻頁時修改page indicator
func scrollViewDidScroll(scrollView: UIScrollView) {
pageIndicator?.currentPage = Int(scrollView.contentOffset.x / self.width()) % pageCount
counter = Int(scrollView.contentOffset.x / self.width())
}
//當手動翻頁時停止記時
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
timer?.invalidate()
}
//當手動翻頁停止時重新開始計時
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
setUpAutoScrollTimer()
}
}
//MARK: Collection View Delegate
extension CycleScrollView:UICollectionViewDelegate {
}