取消UIScrollView的慣性滑動

產(chǎn)品經(jīng)理說按照某團(tuán)、某東、某寶的效果實現(xiàn)。我X,我要是能一模一樣的實現(xiàn)別人的效果你覺得我還會待在這里嗎?

通常,需求確定下來,UI出圖之后看到稍微復(fù)雜的頁面后會先到簡書、GitHub、cocoaChina上面去找有沒有。如果有直接照搬過來,如果沒有就有點懵逼了,為什么會這樣?還是基礎(chǔ)知識不扎實,技術(shù)不夠呀!那該怎么辦?平常多思考、多積累唄,不要僅僅當(dāng)一個代碼搬運工,沒有前途??!言歸正傳!


UIScrollView其實是沒有設(shè)置慣性這個屬性的,只能通過代理方法監(jiān)聽滾動的過程,來達(dá)到控制慣性的目的。


控制tableView的滑動,類似美團(tuán)-美食中的地圖列表

首先要明確,通過[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一次拖拽的代理方法執(zhí)行流程

以上代理方法,只有真正理解后才能很好的處理跟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/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容