產(chǎn)品經(jīng)理說按照某團(tuán)、某東、某寶的效果實現(xiàn)。我X,我要是能一模一樣的實現(xiàn)別人的效果你覺得我還會待在這里嗎?
通常,需求確定下來,UI出圖之后看到稍微復(fù)雜的頁面后會先到簡書、GitHub、cocoaChina上面去找有沒有。如果有直接照搬過來,如果沒有就有點懵逼了,為什么會這樣?還是基礎(chǔ)知識不扎實,技術(shù)不夠呀!那該怎么辦?平常多思考、多積累唄,不要僅僅當(dāng)一個代碼搬運工,沒有前途??!言歸正傳!
UIScrollView其實是沒有設(shè)置慣性這個屬性的,只能通過代理方法監(jiān)聽滾動的過程,來達(dá)到控制慣性的目的。

首先要明確,通過[scrollView setContentOffset:CGPointZero animated:NO];這個方法設(shè)置UIScrollView的偏移,是不會觸發(fā)UIScrollView的- (void)scrollViewDidScroll:(UIScrollView*)scrollView這個代理方法的。
接下來看一下怎么通過UIScrollView的代理方法達(dá)到取消慣性
1、當(dāng)手指放在屏幕開始拖動前,會先調(diào)用下面的代理方法
- (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView {
? ? ? lastContentOffset = scrollView.contentOffset.y;//用來判斷滾動方向
}
2、滾動中會調(diào)用下面的代理方法
- (void)scrollViewDidScroll:(UIScrollView*)scrollView {
//可以再這個方法里面動態(tài)控制某個控件的隱藏、透明度以及跟隨UIScrollView的偏移而變化位置
? ? ? CGFloatoffsetY? = scrollView.contentOffset.y;
if (offsetY < self.lastContentOffset){//向下滾動
? ? } else if (offsetY >self.lastContentOffset) {//向上滾動
? ? }
}
3、這個是控制慣性滑動的重要方法,手指將要松開時調(diào)用
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint *)targetContentOffset
{
? ? CGFloat speed = fabs(velocity.y);//滾動速度的絕對值,也可以根據(jù)velocity.y的正負(fù)判讀滾動方向 假如為0 說明手動拖動停止 沒有慣性滑動
? ? CGFloat offsetY = scrollView.contentOffset.y;
? ? CGFloat maxSpeed =2.7;//超過這個最大速度要做的操作
? ? if( velocity.y <0) {//向下滑動
? ? ? ? if(speed > maxSpeed && offsetY >0) {//頂部往下滑
? ? ? ? ? ?[self performSelectorOnMainThread:@selector(stopOnTop:) withObject:scrollView waitUntilDone:NO];//一定要在主線程立即執(zhí)行 和 runLoop有關(guān)
? ? ? ? }
? ? }
? ? else {//向上滑動
? ? }
}
- (void)stopOnTop:(UIScrollView *)scrollView {//在頂部停止?jié)L動
? ? [self.tableView setContentOffset:CGPointZero animated:YES];
}
4、手指已經(jīng)松開會調(diào)用這個代理方法
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {//decelerate為YES 說明有滑動 NO沒有滑動 直接停止
if (!decelerate) {//手指控制 直接停止 也就是拖動一段距離直接停止
? ? ? ? BOOLdragToDragStop = scrollView.tracking && !scrollView.dragging && !scrollView.decelerating;
? ? ? ? if(dragToDragStop) {// 停止后要執(zhí)行的代碼
? ? ? ? ? ? [self scrollViewEndScroll:scrollView];
? ? ? ? }
? ? }
}
5、減速結(jié)束會調(diào)用這個方法,并不是就一定等于滑動結(jié)束了。因為有些滑動并不需要減速也可以結(jié)束,比如我兩只手輪流向左滑動,直到滑動到scrollview的右側(cè)盡頭為止,這個過程的滑動是被迫終止而不是自然減速停止,這樣scrollViewDidEndDecelerating方法是不會被執(zhí)行的
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
BOOLscrollToScrollStop = !scrollView.tracking && !scrollView.dragging && !scrollView.decelerating;//為YES 表示滾動結(jié)束
? ? if(scrollToScrollStop) {// 停止后要執(zhí)行的代碼
? ? ? [self scrollViewEndScroll:scrollView];
? ? }
}
- (void)scrollViewEndScroll:(UIScrollView *)scrollView { //完全停止?jié)L動要做的處理
}

以上代理方法,只有真正理解后才能很好的處理跟ScrollView滾動相關(guān)的事件!
下面補充一些小的知識點
self.tableView.decelerationRate = UIScrollViewDecelerationRateFast; ? ?//這個屬性用來調(diào)節(jié)scrollView的滾動速度
? ? ?int abs(int i);? ? ? ? ? ? ? ? ? //處理int類型的取絕對值
?? ? double fabs(double i);//處理double類型的取絕對值
?? ? float fabsf(float i);? ? ? ? ? /處理float類型的取絕對值
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(- 104, 0, 0, 0);//設(shè)置滾動條的偏移量,如果發(fā)現(xiàn)豎向滾動條錯亂,一般和scrollView的automaticallyAdjustsScrollViewInsets 屬性有關(guān),設(shè)置為NO即可
參考資料:
https://tech.glowing.com/cn/practice-in-uiscrollview/