輪播圖現(xiàn)在基本已經(jīng)是app的標準配件之一了幕随。一個實用的輪播圖控件無疑能在很大程度上提高我們的開發(fā)效率尘盼。擼主自己封裝了一個簡易的bannerView。
使用sd加載圖片抖僵,支持 horizontal 和 vertical 兩個滾動方向,可以設置 isAutoScroll 和自動滾動的duration 和媳。
這里將思路和關鍵代碼分享給大家砚婆。
循環(huán)滾動的思路如下圖:
1.如果只有一張圖淆珊,返回一個cell并展示這張圖
2.如果有多個圖,cell的個數(shù)=圖片個數(shù)+2.
3.展示的時候 第一個cell 展示最后一張圖 最后一個cell 展示第一張圖健芭,其他的cell按順序展示圖片县钥。
4.collectionView的起始偏移量設置為collectionView的width (滾動到第二個cell的位置)。
5.向右滑動collectionView慈迈,當滾動到(最后一個cell完全展示出來)最后一個cell時無動畫滾回第二個cell若贮,向左滑動,當滾動到第一個cell時痒留,無動畫滾動到倒數(shù)第二個cell谴麦。
6.如果設置的是自動滾動,則添加定時器伸头,每隔一段時間自動滾動到下一頁匾效。
?1.2.對應code:
func collectionView(_ collectionView:UICollectionView, numberOfItemsInSection section: Int) -> Int {
if(self.imgArr?.count)! >1{
return(self.imgArr?.count)! +2
? ? ? ? }
return1
? ? }
3.對應code:
func collectionView(_ collectionView:UICollectionView, cellForItemAt indexPath: IndexPath) ->UICollectionViewCell{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID,for: indexPath) as! BannerCollectionCell
cell.placeholder =self.placeholder
ifindexPath.row ==0{
cell.imgUrl =self.imgArr?.last
}elseifindexPath.row == (self.imgArr?.count)! +1{
cell.imgUrl =self.imgArr?.first
}else{
cell.imgUrl =self.imgArr?[indexPath.row -1]
? ? ? ? }
returncell
? ? }
4.對應code:
override func willMove(toSuperview newSuperview:UIView?) {
guard newSuperview !=nilelse{
return
? ? ? ? }
super.willMove(toSuperview: newSuperview)
// 如果imgArr 為 nil return
ifself.imgArr ==nil{
return
? ? ? ? }
guard (self.imgArr?.count)! >1else{
self.collectionView.isScrollEnabled =false
return
? ? ? ? }
scrollTo(crtPage:0+1, animated:false)
ifself.isAutoScroll ==true{
? ? ? ? ? ? addTimer()
? ? ? ? }
? ? }
我這里將滾動到第二個cell的時機設置到了?willMove(toSuperview newSuperview: UIView?)??
5.對應code
func scrollViewDidScroll(_ scrollView:UIScrollView) {
var offset =CGFloat(0)
ifself.mode == .horizontal {
? ? ? ? ? ? offset = scrollView.contentOffset.x
}else{
? ? ? ? ? ? offset = scrollView.contentOffset.y
? ? ? ? }
let x =self.mode == .horizontal ?self.frame.size.width :self.frame.size.height
ifoffset ==0{
scrollTo(crtPage: (self.imgArr?.count)!, animated:false)
self.pageControl.currentPage = (self.imgArr?.count)! -1
}elseifoffset ==CGFloat((self.imgArr?.count)! +1) * x {
scrollTo(crtPage:1, animated:false)
self.pageControl.currentPage =0
}else{
self.pageControl.currentPage = lroundf(Float(offset/self.frame.size.width)) -1
? ? ? ? }
? ? }
6.對應code:
? ? fileprivate func addTimer() {
ifself.timer ==nil{
self.timer = Timer.scheduledTimer(timeInterval:self.duration, target:self, selector:#selector(nextPage), userInfo: nil, repeats: true)
RunLoop.current.add(self.timer!, forMode: RunLoopMode.commonModes)
? ? ? ? }
? ? }
? ? @objc fileprivate func nextPage() {
if(self.imgArr?.count)! >1{
var crtPage =0
ifself.mode == .horizontal {
crtPage = lroundf(Float(self.collectionView.contentOffset.x/self.frame.size.width))
}else{
crtPage = lroundf(Float(self.collectionView.contentOffset.y/self.frame.size.height))
? ? ? ? ? ? }
scrollTo(crtPage: crtPage +1, animated:true)
? ? ? ? }
? ? }
添加定時器后需要在scrollVIew的代理方法里實現(xiàn):
開始拖拽collectionView時停止計時器,停止拖拽后重新啟動定時器恤磷。
func scrollViewWillBeginDragging(_ scrollView:UIScrollView) {
// pause
self.timer?.fireDate = Date.distantFuture
? ? }
func scrollViewDidEndDragging(_ scrollView:UIScrollView, willDecelerate decelerate: Bool) {
// resume
self.timer?.fireDate = Date.init(timeIntervalSinceNow:self.duration)
? ? }
以上就實現(xiàn)循環(huán)滾動的思路面哼。
擼主這里使用的是collectionView,使用起來比較方便簡潔 扫步。還有一種方法是使用 scrollView里面添加3個子view魔策,通過子view的循環(huán)使用來達到類似的效果,其實現(xiàn)思路也類似以上河胎。
完整代碼請移步github:https://github.com/zh-ios/BannerView-Swift.git
如有問題歡迎指出 闯袒。
在code 測試過程發(fā)現(xiàn)一個有意思現(xiàn)象:
? ? ? ? // 注意:下面這兩個屬性有沖突(hidesForSinglePage優(yōu)先級比較高),當設置了pageControl.hidesForSinglePage = true 時游岳,如果不止有一頁那么再設置pageControl.isHidden = true 沒有卵用8橄拧!吭历!堕仔。反之,如果不設置這個屬性則可以通過 isHidden 這個屬性控制pageControll的顯示和隱藏晌区。
? ? ? ? self.pageControl.hidesForSinglePage = true
//? ? ? ? self.pageControl.isHidden = true
這就是所謂的“就近原則”吧摩骨。具體可以參照https://my.oschina.net/zhxx/blog/663226這篇控件對齊方式的博客通贞。
https://blog.csdn.net/weixin_34267123/article/details/91633067