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