iOS仿高德首頁推拉效果實例代碼

上面是實現的效果,滑動的視圖是新建的一個UIView子類

1、滑動view的調用

    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相關配置

    UIPanGestureRecognizer * panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
    panGestureRecognizer.delegate = self;
    [self addGestureRecognizer:panGestureRecognizer];
    self.tableView.bounces = NO;
    self.tableView.userInteractionEnabled = NO;

tableView必須加上上面這兩個屬性

userInteractionEnabled屬性是用來阻止當視圖在底部時禁止tableview上的手勢的,不加這個屬性時會導致視圖在底部時會響應tableview向上滾動的事件,從而導致視圖無法整體向上滑動。當視圖滑到頂部時又需要把userInteractionEnabled設為YES,否則tableview無法向上滾動。如果在底部時tableview並沒有展示出來,展示的隻是一些其他的控件就可以不需要設置這個屬性
bounces設為NO是為瞭阻止tableview滾動到頂部時還能響應自己的向下拉的事件,從而去響應整個視圖的向下滑到手勢。

3、設置允許同時響應多個手勢

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

這個允許同時響應多個手勢是必須的,否則視圖的手勢會被tableview的事件覆蓋掉。

4、滑動相關邏輯處理

1、在scrollViewDidScroll中獲取tableview偏移量,記錄下來

-(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

在視圖滑動過程中對速度和距離做瞭判斷,根據速度和距離將視圖滑動到底部和頂部

- (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

- (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全部註釋掉就可以瞭。

-(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仿高德首頁推拉內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: