美文网首页tom程序员android
仿网易考拉 个人中心 tableView弹簧动画

仿网易考拉 个人中心 tableView弹簧动画

作者: LiYaoPeng | 来源:发表于2018-09-13 19:16 被阅读300次
SpringTableView.gif

demo 下载

1. 思路

  1. 添加给tableView添加一个子view headerView
  2. 调整headerView zPosition 使其z坐标在tableView的最底部
  3. 当tableView 滑动,cell挡住headerView的时候,需要调整headerView的事件相应热区

2. 代码

1. 设置headerView的zPosition:

zPosition就是z轴,它的坐标标度从屏幕内往屏幕外依次递增;

NSInteger zPosition = self.isCoverOnCell ? NSUIntegerMax : -1;     
_headerView.layer.zPosition = zPosition;

2. 调整tableView 的contentInsert

需要保证tableView的顶部露出headerView

 CGFloat top = self.contentInset.top;
        if (CGRectGetMaxY(self.headerViewFrame) < self.bottomHoverY) {
            top -= self.bottomHoverY;
        }else{
            top -= CGRectGetMaxY(self.headerViewFrame);
        }
        self.headerViewFrame = self.headerView.frame;
        top += CGRectGetMaxY(self.headerViewFrame);
        
        CGFloat bottom = self.contentInset.bottom;
        self.contentInset = UIEdgeInsetsMake(top, 0, 0, bottom);

3. tableView滚动的时候需要设置headerView的可点击范围
· 传入热区 范围 属性并依此判断是否应该响应事件

@property (nonatomic,assign) CGRect responseFrame;

· headerView 点击热区需要重写HeaderView的 pointInside:withEvent:方法

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    if ((self.responseFrame.size.height <= 0)
        || (self.responseFrame.size.width <= 0)) {
        return false;
    }
    CGFloat minX1 = CGRectGetMinX(self.frame);
    CGFloat minY1 = CGRectGetMinY(self.frame);
    CGFloat minW1 = CGRectGetWidth(self.frame);
    CGFloat minH1 = CGRectGetHeight(self.frame);

    CGFloat minX2 = CGRectGetMinX(self.responseFrame);
    CGFloat minY2 = CGRectGetMinY(self.responseFrame);
    CGFloat minW2 = CGRectGetWidth(self.responseFrame);
    CGFloat minH2 = CGRectGetHeight(self.responseFrame);
    
    CGFloat minX = minX1 < minX2 ? minX1 : minX2;
    CGFloat minY = minY1 < minY2 ? minX1 : minY2;
    CGFloat minW = minW1 < minW2 ? minW1 : minW2;
    CGFloat minH = minH1 < minH2 ? minH1 : minH2;
    CGRect rect = CGRectMake(minX, minY, minW, minH);
    
    return CGRectContainsPoint(rect, point);
}

4. 添加pan手势监听

根据pan手势的状态来执行动画

 [self addObserver:self forKeyPath:@"panGestureRecognizer.state" options:NSKeyValueObservingOptionNew context:nil];

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    
    if ([keyPath isEqualToString:@"panGestureRecognizer.state"]) {
        CGPoint contentOffset = self.contentOffset;
        switch (self.panGestureRecognizer.state) {
                
            case UIGestureRecognizerStatePossible:
            case UIGestureRecognizerStateBegan:
            case UIGestureRecognizerStateChanged:
                return;
            case UIGestureRecognizerStateEnded:
            case UIGestureRecognizerStateCancelled:
            case UIGestureRecognizerStateFailed:
                break;
        }
        if (self.animationBlock) {
            self.animationBlock(self, self.contentOffset);
            return;
        }
        
        // 弹簧动画,参数分别为:时长,延时,弹性(越小弹性越大),初始速度
        CGFloat animationY = 0;
        //        NSLog(@"%@",NSStringFromCGPoint(contentOffset));
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationRepeatAutoreverses:false];
        if (contentOffset.y > 0) {
            return;
        }
        if (contentOffset.y > -self.headerView.frame.size.height){
            [UIView commitAnimations];
            animationY = -self.midHoverY;
            [self setContentOffset:self.contentOffset animated:false];
        }else{
            animationY = -self.bottomHoverY;
        }
        [UIView animateWithDuration: 0.7 delay:0 usingSpringWithDamping:0.6 initialSpringVelocity:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
            
            [self setContentOffset:CGPointMake(0, animationY) animated:false];
            
        } completion:^(BOOL finished) {
        }];
    }else{
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

5 动画自定义:

/**
 * @brief 松手之后执行需要的动画
 * @warning 警告: 如果实现这个方法,则不会执行默认动画
 */
- (void) customAnimationFunc: (void(^)(SpringTableView *view,CGPoint contentOffset)) block;

3. 坑

  1. 需要在父控件的- (void)dealloc方法中调用 reless方法,否则会产生内存泄露(主要是移除了观察者)
  2. 如果对tableVIew.delegate进行了赋值,那么需要在scrollViewDidScroll: 代理方法中调用 scrolling 方法(内部 协调了headerView的点击热区)
  3. 如果实现了customAnimationFunc:方法,则会覆盖默认动画

demo 下载

相关文章

  • 仿网易考拉 个人中心 tableView弹簧动画

    demo 下载 1. 思路 添加给tableView添加一个子view headerView 调整headerVi...

  • iOS仿网易考拉弹簧效果

    先上网易考拉的效果 思路是下拉的同时改变header视图的高度,主要代码在scrollViewDidScroll代...

  • iOS 动画效果小结

    跳转动画 CA翻转动画 执行动画 动画1 CA弹簧动画 mass:质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉...

  • 动画-仿微博弹簧动画

    老玩微博,最近在研究动画,周末抽空写了个发微博的动画 实现步骤 首先模打出一个控制器 这个控制器用来显示多个按钮。...

  • 一行代码实现headView弹簧拉伸效果

    前言 很多app的个人中心上部的headView都实现了弹簧拉伸的效果,即tableView的top并不随着下拉而...

  • 网易考拉领券中心改版

    设计是针对网易考拉的领券中心进行改版设计,旨在帮助用户快速理领券中心,提高用户活跃度和留存率。通过用户群体特征、用...

  • 网易考拉店主招募

    做网易考拉海购店主,就选×考拉公园×,实战派,有人带! 网易考拉海购引路人阿诺。(微信ZUO578601005) ...

  • 网易考拉

    【网易考拉】AGE20`s 爱纪二十之 爱敬 精华遮瑕粉底 正装12.5克+替换装12.5克 【正品低价】¥158...

  • 网易考拉

    1.网易考拉海购作为以跨境业务为主的综合性电商平台,自成立之初就一直坚持自营为主的运作模式,直接与海外品牌商合作,...

  • 如何加入网易考拉海购成为店主,加盟考拉详细流程

    怎么成为网易考拉店主?网易考拉怎么通过代理赚钱? 先看看考拉店主有什么特权及优势: 1.拥有自己的专属店铺。 2....

网友评论

  • yemoumou:山舞银蛇,原驰蜡象,欲与天公试比高。-简书朋友你好,我是币圈一老友,我的写作方向是区块链和数字货币,初到简书,望多多关照。互粉互赞,已赞,期待您的回赞哦。-됄

本文标题:仿网易考拉 个人中心 tableView弹簧动画

本文链接:https://www.haomeiwen.com/subject/kwdggftx.html