無需修改SDWebImage源代碼遏片,實(shí)現(xiàn)SDWebImage框架下的圖片漸變加載效果

眾所周知绰寞,在SDWebImage框架下想要對圖片在下載和下載過程中的狀態(tài)進(jìn)行處理,需要使用SDWebImageOptions泉手,我們首先看一下SDWebImage中有哪些可選項(xiàng)

typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
    /**
     * By default, when a URL fail to be downloaded, the URL is blacklisted so the library won't keep trying.
     * This flag disable this blacklisting.
     */
    SDWebImageRetryFailed = 1 << 0,

    /**
     * By default, image downloads are started during UI interactions, this flags disable this feature,
     * leading to delayed download on UIScrollView deceleration for instance.
     */
    SDWebImageLowPriority = 1 << 1,

    /**
     * This flag disables on-disk caching
     */
    SDWebImageCacheMemoryOnly = 1 << 2,

    /**
     * This flag enables progressive download, the image is displayed progressively during download as a browser would do.
     * By default, the image is only displayed once completely downloaded.
     */
    SDWebImageProgressiveDownload = 1 << 3,

    /**
     * Even if the image is cached, respect the HTTP response cache control, and refresh the image from remote location if needed.
     * The disk caching will be handled by NSURLCache instead of SDWebImage leading to slight performance degradation.
     * This option helps deal with images changing behind the same request URL, e.g. Facebook graph api profile pics.
     * If a cached image is refreshed, the completion block is called once with the cached image and again with the final image.
     *
     * Use this flag only if you can't make your URLs static with embedded cache busting parameter.
     */
    SDWebImageRefreshCached = 1 << 4,

    /**
     * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for
     * extra time in background to let the request finish. If the background task expires the operation will be cancelled.
     */
    SDWebImageContinueInBackground = 1 << 5,

    /**
     * Handles cookies stored in NSHTTPCookieStore by setting
     * NSMutableURLRequest.HTTPShouldHandleCookies = YES;
     */
    SDWebImageHandleCookies = 1 << 6,

    /**
     * Enable to allow untrusted SSL certificates.
     * Useful for testing purposes. Use with caution in production.
     */
    SDWebImageAllowInvalidSSLCertificates = 1 << 7,

    /**
     * By default, images are loaded in the order in which they were queued. This flag moves them to
     * the front of the queue.
     */
    SDWebImageHighPriority = 1 << 8,
    
    /**
     * By default, placeholder images are loaded while the image is loading. This flag will delay the loading
     * of the placeholder image until after the image has finished loading.
     */
    SDWebImageDelayPlaceholder = 1 << 9,

    /**
     * We usually don't call transformDownloadedImage delegate method on animated images,
     * as most transformation code would mangle it.
     * Use this flag to transform them anyway.
     */
    SDWebImageTransformAnimatedImage = 1 << 10,
    
    /**
     * By default, image is added to the imageView after download. But in some cases, we want to
     * have the hand before setting the image (apply a filter or add it with cross-fade animation for instance)
     * Use this flag if you want to manually set the image in the completion when success
     */
    SDWebImageAvoidAutoSetImage = 1 << 11
};

可以看出黔寇,最接近我們所需要的「漸變」效果的,就是這個(gè)SDWebImageProgressiveDownload斩萌,這確實(shí)是一個(gè)逐步顯示圖片的過程缝裤,但是這個(gè)類型所完成的效果,僅僅是一個(gè)從上到下逐漸顯示的效果颊郎,離我們需要的「漸變」效果相差甚遠(yuǎn)憋飞。所以說的直白一些,SDWebImage這個(gè)框架目前是不支持大多數(shù)主流成熟框架均支持的圖片加載「漸變」效果的姆吭。

這樣一來搀崭,要想實(shí)現(xiàn)「漸變」效果,我們似乎只剩下兩條路可以走:

1.替換庫猾编,如YYImage等

  • 優(yōu)點(diǎn):框架自帶支持瘤睹,無需使用者自己處理,方便快捷省事
  • 缺點(diǎn):顯然答倡,在開發(fā)過程中轰传,突然替換基礎(chǔ)庫的成本是很高的,尤其是在DeadLine為期不遠(yuǎn)的時(shí)候瘪撇。如果團(tuán)隊(duì)中有人不熟悉新庫获茬,那么還會(huì)額外衍生學(xué)習(xí)時(shí)間成本,這對快速迭代來說倔既,是很難接受的一件事

2.對SDWebImage進(jìn)行修改恕曲,手動(dòng)完成對「漸變」效果的支持

  • 優(yōu)點(diǎn):節(jié)省了更換其他庫的時(shí)間成本,降低了替換庫所造成的風(fēng)險(xiǎn)和回歸測試的成本
  • 缺點(diǎn):可能需要對源代碼進(jìn)行修改渤涌,如果是使用CocoaPods集成的佩谣,那就很麻煩了

這么對比一看,似乎每一條路的成本都不低实蓬,難道真的只剩下這兩條路可以走了嗎茸俭?

答案是: NO

我看到大多數(shù)文章對于SDWebImage實(shí)現(xiàn)漸變效果的處理方式都是修改源碼,這個(gè)做法實(shí)在是太Low了??安皱,任何需要修改成熟開源框架源碼才能完成的事情调鬓,都是最爛的思路和做法。SDWebImage既然能夠成為適用范圍最廣酌伊,最主流的網(wǎng)絡(luò)圖片框架之一腾窝,其對各種情況和需求的支持力度必然不可能如此局限。即使它不直接支持,那么我們?yōu)楹尾粨Q個(gè)思路和做法呢虹脯?SDWebImage提供的方法如此豐富驴娃,何必要局限于一種,下面我們就來看看如何在不修改SDWebImage源碼的情況下归形,來達(dá)到圖片加載的「漸變」效果托慨,Let's go!

首先,我們不妨可以先思考一下什么是「漸變」效果:無非就是隨著圖片的加載逐漸由模糊到清晰的顯示出來暇榴,這種效果完全可以通過一個(gè)簡單的CATransition動(dòng)畫來完成厚棵,唯一的“難點(diǎn)”不過是這個(gè)動(dòng)畫是add和remove的時(shí)機(jī)而已,大多數(shù)此類解決方案都是直接把這個(gè)簡單的動(dòng)畫效果嵌入SDWebImage源碼中蔼紧,這個(gè)做法不僅Low婆硬,而且對SDWebImage源碼也帶來了傷害,最重要的是奸例,如果你繼續(xù)用這個(gè)庫彬犯,難道每次SDWebImage升級你都要再修改一遍源碼嗎,exm???

所以查吊,通過修改SDWebImage源碼來嵌入這種動(dòng)畫的開發(fā)者谐区,幾乎可以肯定,全都是對CAAnimation基礎(chǔ)完全不熟悉的人逻卖。只要是對CAAnimation熟悉的開發(fā)者都會(huì)知道宋列,CAAnimationDelegate協(xié)議中提供了一個(gè)animationDidStop(_ anim: CAAnimation, finished flag: Bool)方法,該方法可以根據(jù)Animation的key對所有基于CAAnimation的動(dòng)畫進(jìn)行監(jiān)聽操作评也。這么一來炼杖,我們接下來要做什么,你是不是就很明白了呢盗迟。

我們可以來看一下SDWebImage提供的加載網(wǎng)絡(luò)圖片的方法中坤邪,是有當(dāng)圖片完成后的回調(diào)方法的,如:

/**
 * Set the imageView `image` with an `url`, placeholder and custom options.
 *
 * The download is asynchronous and cached.
 *
 * @param url            The url for the image.
 * @param placeholder    The image to be set initially, until the image request finishes.
 * @param options        The options to use when downloading the image. @see SDWebImageOptions for the possible values.
 * @param completedBlock A block called when operation has been completed. This block has no return value
 *                       and takes the requested UIImage as first parameter. In case of error the image parameter
 *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
 *                       indicating if the image was retrieved from the local cache or from the network.
 *                       The fourth parameter is the original image url.
 */
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;

我們可以在SDWebImageCompletionBlock這個(gè)Block塊中來實(shí)現(xiàn)我們的CATransition動(dòng)畫

/*
*  @param options: 選擇.lowPriority(oc中是SDWebImageLowPriority)罚缕,是為了禁止在UI交互過程中啟動(dòng)圖像下載艇纺,保證列表流暢性。例如怕磨,導(dǎo)致UIScrollView減速的下載延遲
*
*
*/
imageView.sd_setImage(with: theUrl as URL, placeholderImage: UIImage.init(named: "newVote_ placeholder"), options: .lowPriority, completed: { [weak self] (image, error, cacheType, url) in
   guard let strongSelf = self else { return }
   if cacheType == .none { // 只有當(dāng)緩存中沒有圖片喂饥,也就是首次加載時(shí)才實(shí)現(xiàn)CATransition動(dòng)畫
      let transition:CATransition = CATransition()
      transition.type = kCATransitionFade // 褪色效果,漸進(jìn)效果的基礎(chǔ)
      transition.duration = 0.85
      transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut) // 先慢后快再慢 
      strongSelf.layer.add(transition, forKey: "newVoteTimeline") // 在layer中加入動(dòng)畫肠鲫,并約定好該動(dòng)畫的key
   }
})

我們來解釋一下上面這段代碼究竟做了什么:

options: 選擇.lowPriority(oc中是SDWebImageLowPriority),是為了禁止在UI交互過程中啟動(dòng)圖像下載或粮,保證列表流暢性导饲。例如,導(dǎo)致UIScrollView減速的下載延遲

判斷cacheType == .none: 只有當(dāng)緩存中沒有圖片,也就是首次加載時(shí)才實(shí)現(xiàn)CATransition動(dòng)畫渣锦,因?yàn)镾DWebImage會(huì)根據(jù)url從緩存中查找是否存在相同的圖片硝岗,只有當(dāng)緩存中不存在該圖片時(shí)才會(huì)啟動(dòng)下載,同理袋毙,我們的「漸變」效果也是只有當(dāng)啟動(dòng)下載是才會(huì)發(fā)生型檀,否則,在列表中復(fù)用時(shí)會(huì)持續(xù)顯示「漸變」效果听盖,無論是否已經(jīng)下載完成

然后胀溺,我們遵循CAAnimationDelegate協(xié)議,并實(shí)現(xiàn)animationDidStop(_ anim: CAAnimation, finished flag: Bool)方法:

// MARK: 監(jiān)聽漸變動(dòng)畫是否已完成
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
   if flag {
      self.layer.removeAnimation(forKey: "newVoteTimeline") // 當(dāng)newVoteTimeline動(dòng)畫已經(jīng)完成皆看,將其從layer中移除仓坞,避免復(fù)用中的產(chǎn)生反復(fù)「漸變」效果
   }
}

以上就完成了針對SDWebImage框架的「漸變」效果修改,幾行代碼即可搞定腰吟,完全不需要對SDWebImage進(jìn)行內(nèi)部修改无埃,有時(shí)候換一種思路思考問題,世界會(huì)豁然開朗毛雇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嫉称,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子灵疮,更是在濱河造成了極大的恐慌织阅,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件始藕,死亡現(xiàn)場離奇詭異蒲稳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)伍派,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門江耀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诉植,你說我怎么就攤上這事祥国。” “怎么了晾腔?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵舌稀,是天一觀的道長。 經(jīng)常有香客問我灼擂,道長壁查,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任剔应,我火速辦了婚禮睡腿,結(jié)果婚禮上语御,老公的妹妹穿的比我還像新娘。我一直安慰自己席怪,他們只是感情好应闯,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著挂捻,像睡著了一般碉纺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刻撒,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天骨田,我揣著相機(jī)與錄音,去河邊找鬼疫赎。 笑死盛撑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捧搞。 我是一名探鬼主播抵卫,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胎撇!你這毒婦竟也來了介粘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤晚树,失蹤者是張志新(化名)和其女友劉穎姻采,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體爵憎,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡慨亲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宝鼓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刑棵。...
    茶點(diǎn)故事閱讀 40,615評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖愚铡,靈堂內(nèi)的尸體忽然破棺而出蛉签,到底是詐尸還是另有隱情,我是刑警寧澤沥寥,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布碍舍,位于F島的核電站,受9級特大地震影響邑雅,放射性物質(zhì)發(fā)生泄漏片橡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一淮野、第九天 我趴在偏房一處隱蔽的房頂上張望锻全。 院中可真熱鬧狂塘,春花似錦录煤、人聲如沸鳄厌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽了嚎。三九已至,卻和暖如春廊营,著一層夾襖步出監(jiān)牢的瞬間歪泳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工露筒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呐伞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓慎式,卻偏偏與公主長得像伶氢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子瘪吏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫癣防、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,121評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,302評論 25 707
  • ??IDE:Android Studio??無法使用Recyclerview掌眠,android.support.v7...
    arousalzk閱讀 4,857評論 0 0
  • 后臺數(shù)據(jù)管理 后臺采用的Parse.com蕾盯,真的好好用!而且guide寫得超級好蓝丙,連界面都模仿的蘋果的風(fēng)格级遭,行文清...
    _lemon閱讀 457評論 0 0
  • 炎炎夏日,接到七歲侄女打來的電話約我去游泳渺尘。侄女住的小區(qū)的樓下有個(gè)室外的游泳池挫鸽,很方便播演〔⑴牵酷暑難耐,我欣然答...
    靈清的玉閱讀 662評論 0 5