iOS主流个人主页随滚动可缩放头图

效果图

  • 向上滚动图片变窄


    zoomHeaderImageView.gif
  • 向上滚动图片不变


    zoomHeaderImageViewNoNarrow.gif

源码地址在我的github

前言

目前主流APP的个人主页都会在顶部展示一个头图,图片可以由用户自定义设置,不仅彰显了用户的个性,也增加了页面的丰富性;并且头图也可以随着页面的滚动有一种缩放的效果,大大的提高了用户的交互性,让用户爱不释手!如果你正在负责这方面的需求,我觉得你应该尝试下这个效果。

实现原理

核心原理很简单,就是UIViewcontentMode属性。针对UIImageView有常用的三种mode:UIViewContentModeScaleToFill
UIViewContentModeScaleAspectFitUIViewContentModeScaleAspectFill,用三个图片展示它们的区别吧。

  • UIViewContentModeScaleToFill 这个就比较暴力了,按着UIImageView的尺寸将图片不按着原图比例填满,所以出现了比较丑的压扁效果。
    UIViewContentModeScaleToFill.png
  • UIViewContentModeScaleToFill将图片进行等比例缩放,直到宽或者高和UIImageView的一样。所以高度先合适,宽度只能留白了。
    UIViewContentModeScaleAspectFit.png
  • UIViewContentModeScaleAspectFill将图片进行等比例缩放,直到填满整个UIImageView,这个效果正是我们想要的。
    UIViewContentModeScaleAspectFill.png

综上所述,我们将UIImageView.contentMode设置为UIViewContentModeScaleAspectFill,然后随着滚动的offsetY去更新UIImageView的y和height就行了。

代码展示

我们开发的时候,对于视图的布局一般有三种方式:

  • 直接设置视图的frame,不进行约束;

  • 使用代码约束,常用的masonry;

  • 使用xib约束;
    选择不同的布局方式,在实现效果的细节上也是不一样的,所以我针对这三种方式进行分别展示。当你的项目选择一种适合的布局方式,然后选择效果的实现方式即可。

  • 直接设置视图的frame,不进行约束

初始化视图
- (void)initUINoConstraint
{
    UIImageView *headerImageView = [[UIImageView alloc] initWithFrame:self.bounds];
    headerImageView.clipsToBounds = YES;
    headerImageView.contentMode = UIViewContentModeScaleAspectFill;
    headerImageView.image = [UIImage imageNamed:@"lufei.jpg"];
    [self addSubview:headerImageView];
    self.headerImageView = headerImageView;
    self.originalHeaderImageViewFrame = self.bounds;
}
根据offsetY更新布局
- (void)updateHeaderImageViewFrameWithOffsetY:(CGFloat)offsetY
{
//防止height小于0
            if (self.originalHeaderImageViewFrame.size.height - offsetY < 0) {
                return;
            }
            //如果不使用约束的话,图片的y值要上移offsetY,同时height也要增加offsetY
            CGFloat x = self.originalHeaderImageViewFrame.origin.x;
            CGFloat y = self.originalHeaderImageViewFrame.origin.y + offsetY;
            CGFloat width = self.originalHeaderImageViewFrame.size.width;
            CGFloat height = self.originalHeaderImageViewFrame.size.height - offsetY;
            self.headerImageView.frame = CGRectMake(x, y, width, height);
}
  • 使用代码约束,常用的masonry
初始化视图
- (void)initUICodeConstraint
{
    UIImageView *headerImageView = [[UIImageView alloc] init];
    headerImageView.clipsToBounds = YES;
    headerImageView.contentMode = UIViewContentModeScaleAspectFill;
    headerImageView.image = [UIImage imageNamed:@"lufei.jpg"];
    [self addSubview:headerImageView];
    self.headerImageView = headerImageView;
    //约束设置为:跟父视图左、下、右贴紧,再约束高度,所以更新高度约束的时候会向上增加,xib约束同理
    [headerImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.and.bottom.equalTo(self).offset(0);
        self.codeConstraintHeight = make.height.equalTo(@(self.bounds.size.height));
    }];
    self.originalHeaderImageViewHeight = self.bounds.size.height;
}
根据offsetY更新布局
- (void)updateHeaderImageViewFrameWithOffsetY:(CGFloat)offsetY
{
//防止height小于0
            if (self.originalHeaderImageViewHeight -offsetY < 0) {
                return;
            }
            //第一种方式:获取到这个约束,直接对约束值修改
            //self.codeConstraintHeight.equalTo(@(self.originalHeaderImageViewHeight -offsetY));
            //第二种方式:直接使用masonry提供的更新约束方法,其实原理是一样的
            [self.headerImageView mas_updateConstraints:^(MASConstraintMaker *make) {
                make.height.equalTo(@(self.originalHeaderImageViewHeight -offsetY));
            }];
}
  • 使用xib约束
//需要将xib中的高度约束用拉线拉出来
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *layoutHeightOfHeaderImageView;
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        self.isNeedNarrow = YES;
        [self initUIXibConstraint];
    }
    return self;
}
根据offsetY更新布局
- (void)updateHeaderImageViewFrameWithOffsetY:(CGFloat)offsetY
{
//防止height小于0
            if (self.originalHeaderImageViewHeight -offsetY < 0) {
                return;
            }
            self.layoutHeightOfHeaderImageView.constant = self.originalHeaderImageViewHeight - offsetY;
}
  • 向上滚动图片是否变窄的实现
//用于实现向上滚动的时候,图片不变窄
- (void)updateHeaderImageViewFrameWithOffsetY:(CGFloat)offsetY
{
    if (!self.isNeedNarrow && offsetY > 0) {
        return;
    }
}

外部使用

    //没有约束
//    ZoomHeaderView *headerView = [[ZoomHeaderView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 300) type:ZoomHeaderViewTypeNoConstraint];
    //代码约束
//    ZoomHeaderView *headerView = [[ZoomHeaderView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 300) type:ZoomHeaderViewTypeCodeConstraint];
    //xib约束
    ZoomHeaderView *headerView = [[[NSBundle mainBundle] loadNibNamed:@"ZoomHeaderView" owner:nil options:nil] lastObject];
    //可以对比看效果
//    headerView.isNeedNarrow = NO;
    tableView.tableHeaderView = headerView;
    self.headerView = headerView;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat offsetY = scrollView.contentOffset.y;
    [self.headerView updateHeaderImageViewFrameWithOffsetY:offsetY];
}

总结

总得来说,代码还是比较简单的,可以快捷实现滚动缩放的效果,只是要注意一些细节设置,欢迎大家去我的github,下载源码进行查看。如何我的描述中有什么纰漏或者错误的地方,麻烦各位大神多多指正!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容

  • -- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实...
    翘楚iOS9阅读 2,806评论 0 13
  • 每天读一遍,连续21天,你将获得宇宙无限的正能量 从今天开始的每一天 我已经改变成为一个全新的人 我充满了灵性和爱...
    龚嘉淇阅读 421评论 0 0
  • 修改配置文件:-Xms512m-Xmx2048m-XX:MaxPermSize=768-XX:ReservedCo...
    goodl阅读 215评论 0 1
  • 从今儿开始记录我的营养早餐, 今儿心情很美丽,只因有阳光。 化个妆,即便不出门也要美美哒! 女为悦己者容,是一种顺...
    朱莉叶6666阅读 213评论 0 0
  • 你的自制力如何?哈哈,有没有对生活有些规划,有没有经常拖沓,有没有生活目标和实现的愿望,有没有很想去的远方,有没有...
    蘑菇乐阅读 655评论 0 0