美文网首页代码片段键盘上的鼓手iOS
iOS之下拉放大,上推缩小,一个方法搞定

iOS之下拉放大,上推缩小,一个方法搞定

作者: CrazySteven | 来源:发表于2016-07-26 23:33 被阅读4587次

    最近加班加的比较多,再加上这个真的比较考验逻辑,所以一段时间都没写东西了。来说说这次的功能,网上有很多类似的demo,但都是分开实现的,我把这两个功能放到了一起,并且没有使用AutoLayout,没有用KVO,没有用storyboard/xib.除了逻辑有点绕(现在不是流行玩算法么,那就搞的难理解点吧。。。),其他的还是简单易懂的,而且我将重点数字使用的宏定义,扩展性很强。

    先来看看效果吧。

    讲讲大概的实现思路:
    1、创建头部的视图和tableview,需要注意的是tableview要设置contentInset,contentInsent 的顶部要和头部视图的背景图的高度一样,否则会有空隙(或是有遮挡)。
    myTableView.contentInset = UIEdgeInsetsMake(headRect.size.height-navHeight-navHeight, 0, 0, 0);
    2、对头部视图的背景图片的尺寸进行处理,当然,你也可以直接找一个适合尺寸的图片,就不用处理图片了,为了增加程序的扩展性,我就随便选了张图,并进行图片尺寸处理。

      UIImage * image = [UIImage imageNamed:name];
      UIImage * newImg = [self image:image byScalingToSize:self.bounds.size];
      backgroundView.image = newImg;
      backgroundView.clipsToBounds = YES;//切掉图片多余的部分
    
    //处理图片方法
    - (UIImage *)image:(UIImage*)image byScalingToSize:(CGSize)targetSize {
        UIImage *sourceImage = image;
        UIImage *newImage = nil;
        
        UIGraphicsBeginImageContext(targetSize);
        
        CGRect thumbnailRect = CGRectZero;
        thumbnailRect.origin = CGPointZero;
        thumbnailRect.size.width  = targetSize.width;
        thumbnailRect.size.height = targetSize.height;
        
        [sourceImage drawInRect:thumbnailRect];
        
        newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        return newImage ;
    }
    
    

    3.搞定了这些,准备工作就完成了,接下来,一个方法实现我们的下拉放大、上推缩小的功能,当然,重点和难点是逻辑,技术很easy。大家都知道UITableView是继承UIScrollView的,利用UIScrollView的代理方法- (void)scrollViewDidScroll:(UIScrollView *)scrollView;来实现。

    下拉放大

    在这个方法中,我们将功能分为两部分,一个是下拉放大,这个是比较容易的,就是对头部视图的背景图进行放大,调整frame,需要注意的是在此需要调整图片的显示方式,因为下拉和上推中图片显示的方式是不同的,否则即使你调整了frame,也不会按frame来显示的。

      _myView.backgroundView.contentMode = UIViewContentModeScaleToFill;
      
      _myView.backgroundView.frame = CGRectMake(offset_Y*0.5 , -navHeight, VCWidth - offset_Y, headRect.size.height - offset_Y);
    
    
    上推移动缩小

    这个就比较难理解了,当然,我说的是中间对frame的算法,我们将三个视图分开说。

    • 背景图:先切换显示模式,然后将y随着tableview偏移移动到0,高度也是随着tableview偏移,最终移动到需要的高度(Demo留的是44)
      _myView.backgroundView.contentMode = UIViewContentModeTop;
    
      _myView.backgroundView.frame = CGRectMake(0 ,navHeight* offset_Y/(headRect.size.height-navHeight-navHeight)-navHeight; , VCWidth , headRect.size.height -(navHeight + navHeight* offset_Y/(headRect.size.height-navHeight-navHeight)-navHeight;) - offset_Y);
    
    • 头像:头像需要随着tableview的偏移而移动自身的位置,并且还要进行缩小。这里面就是一个线性方程的关系,和上面的的背景图是一样的。
      CGFloat width = offset_Y*(40-(VCWidth / 4))/(headRect.size.height-navHeight-navHeight)+(VCWidth / 4);
      _myView.headView.frame =CGRectMake(0, 0, width,width);
      _myView.headView.layer.cornerRadius =width*0.5;
      _myView.headView.center = _myView.backgroundView.center;
    
    • 签名:签名比较简单,只要跟着头像动就行,然后再根据偏移调整自己的透明度就行了。
      _myView.signLabel.frame =CGRectMake(0, CGRectGetMaxY(_myView.headView.frame), VCWidth, 40);
            
      _myView.signLabel.alpha = 1 - (offset_Y*3 / (headRect.size.height-navHeight-navHeight) /2);
    

    然后就大功告成了,里的的逻辑挺麻烦的,但有初中的数学水平就够了,因为都只是简单的线性关系。最后是Demo,欢迎大家Star.

    版权声明:本文为 Crazy Steven 原创出品,欢迎转载,转载时请注明出处!

    相关文章

      网友评论

      • 宏炜:如果头像滑动后不是在背景图中心,而是在中心下面一点,这个怎么写呢?
        宏炜:@CrazySteven 好呢、谢谢
        CrazySteven:@宏炜 约束,用比例
      • 思念那年慕云:加上下拉刷新,头部背景图应该会闪一下吧?
        思念那年慕云:@CrazySteven 我之前加了,会卡顿闪一下。
        CrazySteven:@思念那年慕云 我没有加。。。
      • 5c2ad94c9daf:快速向上滑动时会出现bug
        CrazySteven:@zzy0129 bug已修复,谢谢。
      • 水三叶的刷题日记:自己没发现demo有bug吗
        CrazySteven:@Graphic 没有,请你指正
      • 布里丹之驴:你好,我看了- (void)scrollViewDidScroll:(UIScrollView *)scrollView方法里面没有对scrollView的移动做过处理,也没看到代码哪里做了约束,请问这里是怎么让scrollView跟着上面移动的
        CrazySteven:@小火鸡被取了只好叫别的 UITableView继承UIScrollView.
      • 移动Wek:完整代码Demo有吗
        CrazySteven:@移动Wek 点击蓝色的Demo就可以下载了,欢迎star
      • UNDEFEAT_Wang:楼主,,对你的下拉和上拉的相关计算搞不太明白,,虽然是线性关系 ,但是为什么这么做,是不是一定要这么算,还是觉得问题挺多的。。。
        CGFloat width = offset_Y*(40-(VCWidth / 4))/(headRect.size.height-navHeight-navHeight)+(VCWidth / 4);
        _myView.backgroundView.frame = CGRectMake(offset_Y*0.5 , -navHeight, VCWidth - offset_Y, headRect.size.height - offset_Y);
        _myView.signLabel.frame =CGRectMake(0, CGRectGetMaxY(_myView.headView.frame), VCWidth, 40);

        _myView.signLabel.alpha = 1 - (offset_Y*3 / (headRect.size.height-navHeight-navHeight) /2); ????
        CrazySteven:@OnceAgainMailin 这个比较难以想通的是,当你向上推时,背景图片的高度和origin.y是一起变的。
      • a9c99f65dd58:和mjrefresh结合呢?
        CrazySteven:@伊水古城 自己添加喽。
      • 濤子:应该还要加个offset_Y > (headRect.size.height - navHeight- navHeight)判断,不然就有问题
        CrazySteven:@那位客官 偏移> (headRect.size.height - navHeight- navHeight) 的时候做什么呢?
        濤子:@CrazySteven 就加在那两个判断后面
        CrazySteven:@那位客官 加在哪?
      • WGGHot:兄弟求一份demo cool_wzzer@163.com
        CrazySteven:@wzzer 点击蓝色的Demo就可以下载了
      • Rickie_Lambert:楼主, 你的demo里还是 有bug的啊, 如果向上滚动, 能否把头像的高度固定在状态栏和导航栏的高度, 64, 没到这个位置的时候,tableview的cell 和 headerView应该还可以一起滚动, 不然, headerView就乱停留在了一个位置
        CrazySteven:@Rickie_Lambert 好的,改了可以和我说说,大家共同提高。
        Rickie_Lambert:@CrazySteven 能力有限, 就是感觉偏移的时候有小bug, 不知道怎么改, 菜鸟一个, 先跟你后面学会了, 再进一步改进吧
        CrazySteven:@Rickie_Lambert 向上移动的时候,我三个控件全是移动的。
      • 海边的1984_:我项目使用的是约束:joy::joy:
        CrazySteven:@小小流浪的汉子 下拉放大很多人都用的约束,但上推缩小的时候,很多人用的KVO,然后frame布局
        海边的1984_:@CrazySteven 因为类似的效果找过demo,但是全部都是使用frame计算的,我想能不能用约束计算出来,结果我失败了
        CrazySteven:@小小流浪的汉子 是的,我看很多都使用的约束。。。
      • 五鲜谱:你好,谢谢分享~看完Demo后,有个疑问:HeadView的userInteractionEnabled设置为NO,那上面如何添加有点击事件需求的控件呢?
        CrazySteven:@五鲜谱 我之所以把userInteractionEnabled设为NO,是因为myView挡住了下面的tableview,如果你需要添加有点击事件的控件,那你就不要myView了,直接把控件添加到self.view上。

      本文标题:iOS之下拉放大,上推缩小,一个方法搞定

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