iOS那些“垃圾”的輪播
輪播視圖通常也叫Banner,90%以上App都會用到的一個控件,網上有很多開源代碼,但是至今我覺得比較好的一個是 SDCycleScrollView ,因為他解決了我接下來要吐槽的兩個問題。
通常實現定時自動滾動Banner的思路大體有三種
1. 3個`UIImageView`
2. N+2個`UIImageView`思路
3. N * section(個人不推薦,因為這將代碼寫死了,當有個無聊的人真的滾動到最后一個section時,程序就會crash了)
前兩種思路又分為用 UIScrollView 和 UICollectionView 實現, 個人沒有用過第一種思路,都是第二種,本文也是基于第二種思路 ,這兩種思路的中心思想其實都是運用了 視覺誤差 。
快速滑動時卡頓
先來看看那些“垃圾”Banner
卡頓問題一(3個 UIImageView 思路)
Aiqiyi.gif
Youku.gif
通過卡頓頻率,我猜想這兩個項目的Banner思路應該一樣,用的三個 UIImageView 。
不知道動圖你是否看的卡頓的問題,如果你手機上恰好裝了這兩個App,可以自己試一下,很簡單,只要快速滑動就可以了。
但是這兩個的PageControl還是處理得很好的,能實時滾動到相應的位置。
卡頓問題二((N+2)個 UIImageView 思路)
Tianmao.gif
這個問題不好看出,因為他的卡頓頻率比較低,剛好是一組輪播視圖的周期。必須在第N+1張時才會復現。想看得清楚的小伙伴,如果自己項目Banner是這個思路可以測試一下自己項目的。
再看看這個PageControl的位置,在你快速滑動時,它是不動的,我猜想他控制PageControl的位置應該是在這個方法里做的
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { }
卡頓原因
就是這個兩個方法其中一個里計算cell位置的判斷條件不對
func scrollViewDidScroll(_ scrollView: UIScrollView) { }
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { }
Tab切換卡中間,不能復位
由于這個問題比較難復現,我就用自己的Demo測試的
UICollectionView實現,會自動修復
Test.gif
UIScrollView實現,需手動修復
HalfScreen.gif
動圖中應該可以清楚的看到滾動視圖滾動的坐標不對。
原因
這個具體原因我也不知道,這是所有輪播都會發生的問題,我猜想是跟內部的RunLoop應該有關。
還有的Banner是pageControl和cell聯動不及時,比如 咸魚
因為是在這里處理控制pageControl的位置的
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { }
簡書Banner的pageControl向左手動拖動時又太靈敏。
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let page = scrollView.contentOffset.x / scrollView.frame.width
if page <= 0.0 {
// 向右拉
collectionView?.scrollToItem(at: IndexPath(item: urlStrs.count - 2, section: 0), at: .centeredHorizontally, animated: false)
pageControl?.currentPage = urlStrs.count - 3
} else if page >= CGFloat(urlStrs.count - 1) {
// 向左
pageControl?.currentPage = 0
collectionView?.scrollToItem(at: IndexPath(item: 1, section: 0), at: .centeredHorizontally, animated: false)
} else {
let value = page.truncatingRemainder(dividingBy: 1) < 0.5
if value { // cell過半才改變pageControl(簡書的Banner應該沒有這個判斷)
pageControl?.currentPage = Int(page) - 1
}
}
}
來自:http://www.jianshu.com/p/97037c126d7c