上面是實現的效果,滑動的視圖是新建的一個UIView子類
1、滑動view的調用
1
2
3
|
SlideView * slideView = [[SlideView alloc] initWithFrame:CGRectMake( 0 , kScreenHeight- 140 , kScreenWidth, kScreenHeight- 100 )]; slideView.topH = 100 ; [self.view addSubview:slideView]; |
SlideView是新建的一個UIView子類
kScreenHeight屏幕高
kScreenWidth屏幕寬
topH是視圖滑動到頂部時距離屏幕頂部的距離
注意點:SlideView的高應該是屏幕的高減去topH,否則視圖滑到頂部時高會有點不適配的問題
2、為視圖添加滑動手勢和tableview相關配置
1
2
3
|
UIPanGestureRecognizer * panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action: @selector (panAction:)]; panGestureRecognizer.delegate = self; [self addGestureRecognizer:panGestureRecognizer]; |
1
2
|
self.tableView.bounces = NO; self.tableView.userInteractionEnabled = NO; |
tableView必須加上上面這兩個屬性
userInteractionEnabled屬性是用來阻止當視圖在底部時禁止tableview上的手勢的,不加這個屬性時會導致視圖在底部時會響應tableview向上滾動的事件,從而導致視圖無法整體向上滑動。當視圖滑到頂部時又需要把userInteractionEnabled設為YES,否則tableview無法向上滾動。如果在底部時tableview并沒有展示出來,展示的只是一些其他的控件就可以不需要設置這個屬性
bounces設為NO是為了阻止tableview滾動到頂部時還能響應自己的向下拉的事件,從而去響應整個視圖的向下滑到手勢。
3、設置允許同時響應多個手勢
1
2
3
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } |
這個允許同時響應多個手勢是必須的,否則視圖的手勢會被tableview的事件覆蓋掉。
4、滑動相關邏輯處理
1、在scrollViewDidScroll中獲取tableview偏移量,記錄下來
1
2
3
4
5
|
-( void )scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat currentPostion = scrollView.contentOffset.y; self.stop_y = currentPostion; } |
2、滑動手勢的處理
self.top是視圖的self.frame.origin.y,我這邊是寫在了分類中。
self.bottomH在視圖初始時將self.top賦值給了self.bottomH
在視圖滑動過程中對速度和距離做了判斷,根據速度和距離將視圖滑動到底部和頂部
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
- ( void )panAction:(UIPanGestureRecognizer *)pan { // 獲取視圖偏移量 CGPoint point = [pan translationInView:self]; // stop_y是tableview的偏移量,當tableview的偏移量大于0時則不去處理視圖滑動的事件 if (self.stop_y> 0 ) { // 將視頻偏移量重置為0 [pan setTranslation:CGPointMake( 0 , 0 ) inView:self]; return ; } // self.top是視圖距離頂部的距離 self.top += point.y; if (self.top < self.topH) { self.top = self.topH; } // self.bottomH是視圖在底部時距離頂部的距離 if (self.top > self.bottomH) { self.top = self.bottomH; } // 在滑動手勢結束時判斷滑動視圖距離頂部的距離是否超過了屏幕的一半,如果超過了一半就往下滑到底部 // 如果小于一半就往上滑到頂部 if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled) { // 滑動速度 CGPoint velocity = [pan velocityInView:self]; CGFloat speed = 350 ; if (velocity.y < -speed) { [self goTop]; [pan setTranslation:CGPointMake( 0 , 0 ) inView:self]; return ; } else if (velocity.y > speed){ [self goBack]; [pan setTranslation:CGPointMake( 0 , 0 ) inView:self]; return ; } if (self.top > kScreenHeight/ 2 ) { [self goBack]; } else { [self goTop]; } } [pan setTranslation:CGPointMake( 0 , 0 ) inView:self]; } |
3、滑動到底部和頂部的事件
滑到底部時需要userInteractionEnabled設為NO,取消掉tableview的響應事件。滑到頂部時再將userInteractionEnabled設為YES
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
- ( void )goTop { [UIView animateWithDuration:0.5 animations:^{ self.top = self.topH; }completion:^( BOOL finished) { self.tableView.userInteractionEnabled = YES; }]; } - ( void )goBack { [UIView animateWithDuration:0.5 animations:^{ self.top = self.bottomH; }completion:^( BOOL finished) { self.tableView.userInteractionEnabled = NO; }]; } |
4、注意點
因為在底部時給tableview的serInteractionEnabled屬性設置了NO,這將導致tableview上的所有事件都被取消了,包括cell的選中。如果想保留這個屬性,則可以在scrollViewDidScroll中增加[scrollView setContentOffset:CGPointMake(0, 0)]
同時將代碼中的serInteractionEnabled全部注釋掉就可以了。
1
2
3
4
5
6
7
8
9
|
-( void )scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat currentPostion = scrollView.contentOffset.y; self.stop_y = currentPostion; if (self.top>self.topH) { [scrollView setContentOffset:CGPointMake( 0 , 0 )]; } } |
至此整個滑動效果就實現了,有興趣的小伙伴可以下載demo看看
總結
到此這篇關于iOS仿高德首頁推拉效果的文章就介紹到這了,更多相關iOS仿高德首頁推拉內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://www.jianshu.com/p/5c0c1059923f