生活随笔
收集整理的這篇文章主要介紹了
使用SVProgressHUD时加入自定义Gif图片
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
??? 在 iOS 開發中說到指示器用的最多的便是 MBP 和 SVP 了,針對于這兩個第三方我個人還是比較偏向后者。比較 MBP 而言 SVP的作者封裝的更加完美一些,接口的設計和使用也更為簡單,但是在使用時還是有些場景無法滿足,這篇文章我只是想談談對于把自定義的 GIF 圖片與 SVProgressHUD 結合使用的個人想法。首先我們先看看下面的一段代碼:
- (void)viewDidLoad {[super viewDidLoad];// 我們通過 SVProgressHUD 提供的類方法 + (void)show; 可以實現最簡單的加載指示效果[SVProgressHUD show];}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{// 移除指示器[SVProgressHUD dismiss];
}
??? 效果圖如下 :
? ? 那這個不斷旋轉的圓圈效果是 SVProgressHUD 自帶的Gif圖片嗎?通過多 SVP 中的資源包的查看得知,這個會動的圓圈并不是Gif圖片,而是畫出來的。但是 SVP 是否給我們提供可以傳入 UIImage 對象的方法或是屬性接口呢?我們再來看看下面的代碼和效果:
方案一:通過方法實現
- (void)viewDidLoad {[super viewDidLoad];// 我們讓程序已啟動 就顯示指示器// 設置顯示最小時間 以便觀察效果[SVProgressHUD setMinimumDismissTimeInterval:MAXFLOAT];// 果然 我們發現了一個可以傳入圖片和文字的方法[SVProgressHUD showImage:[UIImage imageNamed:@"testImage@2x.gif"] status:@"努力加載中"];}
方案一:通過屬性實現
- (void)viewDidLoad {[super viewDidLoad];// 設置顯示最小時間 以便觀察效果[SVProgressHUD setMinimumDismissTimeInterval:MAXFLOAT];// 設置屬性 @property (strong, nonatomic) UIImage *infoImage [SVProgressHUD setInfoImage:[UIImage imageNamed:@"testImage@2x.gif"]];[SVProgressHUD showInfoWithStatus:@"努力加載中"];}
但是效果卻不是我們想要的,我們發現原本是 Gif 可以轉動的圖片不能動了... 效果如下 :
??? 其實 Gif 圖片能動的本質是幀動畫,我們在利用軟件制作 Gif 圖片的時候中間有一個步驟是 : 比如將一個小視頻分割成N張圖片,然后按照每張圖片設置好的幀時長來進行連貫播放,優化后就形成了我們所熟知的 Gif 圖片了。那么我們在 iOS 開發過程中能否將原有的 Gif 圖片轉換為N張靜態圖片的數組,再由 UIImage 提供的幀動畫方法生成可以動的 UIImage對象。根據這個想法,我寫了下面的一個分類 :
??? UIImage+GIF.h
#import <UIKit/UIKit.h>
typedef void (^GIFimageBlock)(UIImage *GIFImage);@interface UIImage (GIF)/** 根據本地GIF圖片名 獲得GIF image對象 */
+ (UIImage *)imageWithGIFNamed:(NSString *)name;/** 根據一個GIF圖片的data數據 獲得GIF image對象 */
+ (UIImage *)imageWithGIFData:(NSData *)data;/** 根據一個GIF圖片的URL 獲得GIF image對象 */
+ (void)imageWithGIFUrl:(NSString *)url and:(GIFimageBlock)gifImageBlock;@end
??? UIImage+GIF.m
#import "UIImage+GIF.h"
#import <ImageIO/ImageIO.h>@implementation UIImage (GIF)+ (UIImage *)imageWithGIFData:(NSData *)data
{if (!data) return nil;CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);size_t count = CGImageSourceGetCount(source);UIImage *animatedImage;if (count <= 1) {animatedImage = [[UIImage alloc] initWithData:data];} else {NSMutableArray *images = [NSMutableArray array];NSTimeInterval duration = 0.0f;for (size_t i = 0; i < count; i++) {// 拿出了Gif的每一幀圖片CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);//Learning... 設置動畫時長 算出每一幀顯示的時長(幀時長)NSTimeInterval frameDuration = [UIImage sd_frameDurationAtIndex:i source:source];duration += frameDuration;// 將每幀圖片添加到數組中[images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];// 釋放真圖片對象CFRelease(image);}// 設置動畫時長if (!duration) {duration = (1.0f / 10.0f) * count;}animatedImage = [UIImage animatedImageWithImages:images duration:duration];}// 釋放源Gif圖片CFRelease(source);return animatedImage;
}+ (UIImage *)imageWithGIFNamed:(NSString *)name
{NSUInteger scale = (NSUInteger)[UIScreen mainScreen].scale;return [self GIFName:name scale:scale];
}+ (UIImage *)GIFName:(NSString *)name scale:(NSUInteger)scale
{NSString *imagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@@%zdx", name, scale] ofType:@"gif"];if (!imagePath) {(scale + 1 > 3) ? (scale -= 1) : (scale += 1);imagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@@%zdx", name, scale] ofType:@"gif"];}if (imagePath) {// 傳入圖片名(不包含@Nx)NSData *imageData = [NSData dataWithContentsOfFile:imagePath];return [UIImage imageWithGIFData:imageData];} else {imagePath = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];if (imagePath) {// 傳入的圖片名已包含@Nx or 傳入圖片只有一張 不分@NxNSData *imageData = [NSData dataWithContentsOfFile:imagePath];return [UIImage imageWithGIFData:imageData];} else {// 不是一張GIF圖片(后綴不是gif)return [UIImage imageNamed:name];}}
}+ (void)imageWithGIFUrl:(NSString *)url and:(GIFimageBlock)gifImageBlock
{NSURL *GIFUrl = [NSURL URLWithString:url];if (!GIFUrl) return;dispatch_async(dispatch_get_global_queue(0, 0), ^{NSData *CIFData = [NSData dataWithContentsOfURL:GIFUrl];// 刷新UI在主線程dispatch_async(dispatch_get_main_queue(), ^{gifImageBlock([UIImage imageWithGIFData:CIFData]);});});}#pragma mark - <關于GIF圖片幀時長(Learning...)>+ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {float frameDuration = 0.1f;CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];if (delayTimeUnclampedProp) {frameDuration = [delayTimeUnclampedProp floatValue];}else {NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];if (delayTimeProp) {frameDuration = [delayTimeProp floatValue];}}// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.// We follow Firefox's behavior and use a duration of 100 ms for any frames that specify// a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>// for more information.if (frameDuration < 0.011f) {frameDuration = 0.100f;}CFRelease(cfFrameProperties);return frameDuration;
}
??? 那么引入這個分類,我們看看是否能達到預期的效果,代碼 AND 效果圖如下 :
- (void)viewDidLoad {[super viewDidLoad];// 設置顯示最小時間 以便觀察效果[SVProgressHUD setMinimumDismissTimeInterval:MAXFLOAT];// 設置背景顏色為透明色[SVProgressHUD setBackgroundColor:[UIColor clearColor]];// 利用SVP提供類方法設置 通過UIImage分類方法返回的動態UIImage對象[SVProgressHUD showImage:[UIImage imageWithGIFNamed:@"loading01"] status:@"正在加載中"];}
??? 效果圖如下 :
??? 至此我們簡單的實現了,使用 SVProgressHUD 時加入我們自定義的 Gif 圖片。大家有更好的方法也可以相互討論,共同提高,謝謝支持我的博客 : http://blog.csdn.net/im_loser 。
總結
以上是生活随笔為你收集整理的使用SVProgressHUD时加入自定义Gif图片的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。