iOS中用动画处理解决跳闪情况

不知道大家在访问一些APP的图片时候有没有发现一些跳闪的情况:点击了一张图片之后,它会先显示缩略图,加载完图片之后再显示大图,由于缩略图和大图的大小差距过大,导致加载完成后,突然看到大图的情况,这种情况称为“跳闪”。


跳闪

一.跳闪的引起

“跳闪”并不是一种bug,而是一种引起不好的用户体验的现象,由以下原因引起(需要同时满足以下条件):

  1. 缩略图和原图的尺寸差距非常悬殊
  2. 点击缩略图的时候才开始加载原图
  3. 缩略图变成原图的一瞬间缺乏必要的过渡动画

有很多APP为了避免跳闪情况的出现,在加载图片的过程中并没有选择显示动画,而是显示了加载中的GIF,这是一种解决跳闪的好方法,我称它为鸵鸟算法(手动滑稽)

而经过观察,微信票圈较少出现跳闪现象,这是由以下原因避免的:

  1. 微信采用了边滑动边加载的策略,也就是说,有可能在你点击之前,这张图的原图已经加载完毕了,从而使得点击缩略图的时候,直接用原图的动画显示出来
  2. 即便没有加载完毕,微信的缩略图和原图的尺寸也会保持一致,在加载过程中,会先显示缩略图(即经过压缩的原图),加载完毕后直接显示原图。

即便如此,在微信中也会有一种情况会出现跳闪:

  • 竖型超长图,未加载完毕就点开查看,这时候,会先显示缩略图(一张高度经过极大压缩的图片),加载完成后则会直接显示超长图的顶部。

今天我们就来处理一下这种跳闪的现象:


跳闪处理效果

二.设计思路

1.竖型长图的查看

在上面的GIF中可以看到,竖型长图的过渡非常自然,这是由于缩略图和点击后映入眼帘的视图保持了一致,即两个必要条件:

  1. 缩略图即原图截取的上半部分(无压缩)
  2. 原图显示填充满整个屏幕

第一步是经过服务器实现的,不细说了,第二步则是通过设置MWPhotoBrowser的一个属性实现的:

photoBrowser.zoomPhotosToFill = YES;

这个属性能够确保查看原图的时候能够填充满整个屏幕。

2.横型长图的查看

横向长图是比较容易出现跳闪的情况的,这是因为缩略图和显示的图片显示差距过大,直接跳转则显得极度不自然。


缩略图
原图

这时候,则需要用到动画效果来修补,思路如下:

  1. 原图加载完毕
  2. 将缩略图压缩至原图的高度
  3. 缩略图透明度渐变(由亮变暗)
  4. 缩略图消失
  5. 原图出现
  6. 原图透明度渐变(由暗变亮)

首先怎么知道原图什么时候加载完成?MWPhoto可没有提供这个接口,那么我们就需要阅读一下源码,它到底什么时候加载图片了:

- (void)handleMWPhotoLoadingDidEndNotification:(NSNotification *)notification {
    id <MWPhoto> photo = [notification object];
    MWZoomingScrollView *page = [self pageDisplayingPhoto:photo];
    if (page) {
        if ([photo underlyingImage]) {
            // Successful load
            [page displayImage];
            [self loadAdjacentPhotosIfNecessary:photo];
            if ([self.delegate respondsToSelector:@selector(photoBrowserDidLoadSucceed:zoomScale:)]) {
                [self.delegate photoBrowserDidLoadSucceed:self zoomScale:page.zoomScale];
            }
        }
        else {
            // Failed to load
            [page displayImageFailure];
            if ([self.delegate respondsToSelector:@selector(photoBrowserDidLoadFailed:)]) {
                [self.delegate photoBrowserDidLoadFailed:self];
            }
        }
        // Update nav
        [self updateNavigation];
    }
}

在上面的代码可以看到,在handleMWPhotoLoadingDidEndNotification不仅可以加载图片,还可以顺便获得缩放的大小呢,好的,委托回调知道怎么用了,接下来就看看动画怎么实现了。

参考过很多关于动画的文章,尝试过很多种方案,最终我还是选择使用了继承CABasicAnimationCAAnimationGroup。参考于这篇文章,属性如下:

好的,可以看到我们要用到的值有:

  • transform.scale.y(压缩高度)
  • opacity(透明度渐变)

那么,用动画将他们组合起来就可以了:

//添加动画
CAAnimationGroup *animations = [CAAnimationGroup animation];

CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath: @"opacity"];
animation1.fromValue = [NSNumber numberWithFloat: 1.f];
animation1.toValue = [NSNumber numberWithFloat: .5f];

CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath: @"transform.scale.y"];
animation2.fromValue = [NSNumber numberWithFloat: 1.f];
animation2.toValue = [NSNumber numberWithFloat: zoomScale];

animations.animations = @[animation1, animation2];
animations.duration = .2f;
animations.delegate = self;
animations.removedOnCompletion = NO;
animations.autoreverses = NO;
animations.fillMode = kCAFillModeBoth;
[self.helpImageView.layer addAnimation: animations forKey:@"AnimationKey"];

注意一下,以下这四句话都有自己的意义,具体可以看注释

//结束动画委托
animations.delegate = self;
//需要将其removedOnCompletion设置为NO,要不然fillMode不起作用
animations.removedOnCompletion = NO;
//不逆向
animations.autoreverses = NO;
//动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态.
animations.fillMode = kCAFillModeBoth;

在缩略图动画完成之后(先压缩,后透明),令缩略图消失,并展现原图动画。需要用到动画结束之后的响应函数:

#pragma mark - CAAnimationDelegate

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    if (flag) {
        if ([self.helpImageView.layer animationForKey: @"AnimationKey"] == anim) {
            //恢复至原来的样子
            CAAnimationGroup *animations = [CAAnimationGroup animation];
            CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath: @"opacity"];
            animation1.toValue = [NSNumber numberWithFloat: 1.f];
            CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath: @"transform.scale.y"];
            animation2.toValue = [NSNumber numberWithFloat: 1.f];
            animations.animations = @[animation1, animation2];
            animations.fillMode = kCAFillModeBoth;
            [self.helpImageView.layer addAnimation: animations forKey: @"AnimationKey"];
            [self.helpImageView removeFromSuperview];
            [self.helpImageView.layer removeAllAnimations];
            self.photoBrowser.view.hidden = NO;
            CABasicAnimation *animation4 = [CABasicAnimation animationWithKeyPath: @"opacity"];
            animation4.duration = .2f;
            animation4.fromValue = [NSNumber numberWithFloat: .5f];
            animation4.toValue = [NSNumber numberWithFloat: 1.f];
            [self.photoBrowser.view.layer addAnimation: animation4 forKey:nil];
        }
    }
}

这样就可以按照之前提到的五个点来一步步实现了~

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

推荐阅读更多精彩内容