UIScrollView(包括它的子類 UITableView 和 UICollectionView)是 iOS 開發(fā)中最常用也是最有意思的 UI 組件瓣窄,大部分 App 的核心界面都是基于三者之一或三者的組合實現揖铜。
UIScrollViewDelegate
UIScrollViewDelegate 是 UIScrollView 的 delegate protocol票顾,UIScrollView 有意思的功能都是通過它的 delegate 方法實現的蛋铆。了解這些方法被觸發(fā)的條件及調用的順序對于使用 UIScrollView 是很有必要的,本文主要講拖動相關的效果骨田,所以 zoom 相關的方法跳過不提埠通,拖動相關的 delegate 方法按調用順序分別是:
optional func scrollViewDidScroll(scrollView: UIScrollView)
這個方法在任何方式觸發(fā) contentOffset 變化的時候都會被調用(包括用戶拖動,減速過程晦攒,直接通過代碼設置等)闽撤,可以用于監(jiān)控 contentOffset 的變化,并根據當前的 contentOffset 對其他 view 做出隨動調整脯颜。
optional func scrollViewWillBeginDragging(scrollView: UIScrollView)
用戶開始拖動 scroll view 的時候被調用哟旗。
optional func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
該方法從 iOS 5 引入,在 didEndDragging 前被調用栋操,當 willEndDragging 方法中 velocity 為 CGPointZero(結束拖動時兩個方向都沒有速度)時闸餐,didEndDragging 中的 decelerate 為 NO,即沒有減速過程讼庇,willBeginDecelerating 和 didEndDecelerating 也就不會被調用绎巨。反之,當 velocity 不為 CGPointZero 時蠕啄,scroll view 會以 velocity 為初速度场勤,減速直到 targetContentOffset戈锻。值得注意的是,這里的 targetContentOffset 是個指針和媳,沒錯格遭,你可以改變減速運動的目的地,這在一些效果的實現時十分有用留瞳,實例章節(jié)中會具體提到它的用法拒迅,并和其他實現方式作比較。
optional func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool)
在用戶結束拖動后被調用她倘,decelerate 為 YES 時璧微,結束拖動后會有減速過程。注硬梁,在 didEndDragging 之后前硫,如果有減速過程,scroll view 的 dragging 并不會立即置為 NO荧止,而是要等到減速結束之后屹电,所以這個 dragging 屬性的實際語義更接近 scrolling。
optional func scrollViewWillBeginDecelerating(scrollView: UIScrollView)
減速動畫開始前被調用跃巡。
optional func scrollViewDidEndDecelerating(scrollView: UIScrollView)
減速動畫結束時被調用危号,這里有一種特殊情況:當一次減速動畫尚未結束的時候再次 drag scroll view,didEndDecelerating 不會被調用素邪,并且這時 scroll view 的 dragging 和 decelerating 屬性都是 YES外莲。新的 dragging 如果有加速度,那么 willBeginDecelerating 會再一次被調用兔朦,然后才是 didEndDecelerating苍狰;如果沒有加速度,雖然 willBeginDecelerating 不會被調用烘绽,但前一次留下的 didEndDecelerating 會被調用,所以連續(xù)快速滾動一個 scroll view 時俐填,delegate 方法被調用的順序(不含 didScroll)可能是這樣的:
雖然很少有因為這個導致的 bug安接,但是你需要知道這種很常見的用戶操作會導致的中間狀態(tài)。例如你嘗試在 UITableViewDataSource 的 tableView:cellForRowAtIndexPath: 方法中基于 tableView 的 dragging 和 decelerating 屬性判斷是在用戶拖拽還是減速過程中的話可能會誤判