SVProgressHUD 是一个干净,易于使用的HUD,旨在显示iOS和tvOS正在进行的任务的进展。
常用的还有MBProgressHUD.这两个都是很常用的HUD,大体相似,但是还是有一些不同的.
MBProgressHUD和SVProgressHUD的区别:
svprogresshud 使用起来很方便,但 可定制 差一些,看它的接口貌似只能添加一个全屏的HUD,不能把它添加到某个视图上面去.
MBProgressHUD 功能全一些,可定制 高一些,而且可以指定加到某一个View上去.用起来可能就没上面那个方便了.
具体还要看你的使用场景.
附上GitHub源码地址:
SVProgressHUD:https://github.com/SVProgressHUD/SVProgressHUD
MBProgressHUD:https://github.com/jdg/MBProgressHUD
今天我们不对二者的区别做详解,有空我会专门写文章对它们的区别做一个详解.
今天我们主要简单介绍一下SVProgressHUD的使用.
安装
通过CocoaPods安装,在Podfile
中加入pod 'SVProgressHUD'
,这里不多做介绍.可以参考文章: CocoaPods的简单使用
使用
SVProgressHUD
是已经被创建为单例的,所以不需要被实例化了,可以直接使用.调用它的方法[SVProgressHUD method]
.
[SVProgressHUD show ];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^ {
//耗时的任务
dispatch_async(dispatch_get_main_queue(),^ {
[SVProgressHUD dismiss ];
});
});
显示HUD
可以在下拉刷新或者执行其他耗时任务的时候,使用下面方法之一,来显示不确定任务的状态:
+ (void)show;
+ (void)showWithStatus:(NSString*)string;
效果图分别为:
如果你希望HUD反应任务的进度,可以使用下面方法的其中一个:
+ (void)showProgress:(CGFloat)progress;
+ (void)showProgress:(CGFloat)progress status:(NSString*)status;
通过其他方式可以实现进度条的速度把控.比如:
- (IBAction)clickButtonsShowWithProgress:(id)sender {
progress = 0.0f;
[SVProgressHUD showProgress:0 status:@"Loading"];
[self performSelector:@selector(increaseProgress) withObject:nil afterDelay:0.1f];
}
- (void)increaseProgress {
progress += 0.05f;
[SVProgressHUD showProgress:progress status:@"xuanhe Loading"];
if(progress < 1.0f){
[self performSelector:@selector(increaseProgress) withObject:nil afterDelay:0.1f];
} else {
[self performSelector:@selector(dismiss) withObject:nil afterDelay:0.4f];
}
}
效果如下
还有其他常用的语法:
+(void)showInfoWithStatus :( NSString *)string;
+(void)showSuccessWithStatus :( NSString *)string;
+(void)showErrorWithStatus :( NSString *)string;
+(void)showImage:(UIImage *)image status :( NSString *)string;
取消HUD
HUD可以使用以下方式解除:
+(void)dismiss;
+(void)dismissWithDelay :( NSTimeInterval)delay;
+ (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion;
可以对这些代码进行改进,比如,在弹框结束后执行其他操作.可以封装一个方法,弹框结束后,执行Block.
定制
SVProgressHUD
可以通过以下方法定制:
+ (void)setDefaultStyle:(SVProgressHUDStyle)style; // default is SVProgressHUDStyleLight
+ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType; // default is SVProgressHUDMaskTypeNone
+ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type; // default is SVProgressHUDAnimationTypeFlat
+ (void)setContainerView:(UIView*)containerView; // default is window level
+ (void)setMinimumSize:(CGSize)minimumSize; // default is CGSizeZero, can be used to avoid resizing
+ (void)setRingThickness:(CGFloat)width; // default is 2 pt
+ (void)setRingRadius:(CGFloat)radius; // default is 18 pt
+ (void)setRingNoTextRadius:(CGFloat)radius; // default is 24 pt
+ (void)setCornerRadius:(CGFloat)cornerRadius; // default is 14 pt
+ (void)setBorderColor:(nonnull UIColor*)color; // default is nil
+ (void)setBorderWidth:(CGFloat)width; // default is 0
+ (void)setFont:(UIFont*)font; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]
+ (void)setForegroundColor:(UIColor*)color; // default is [UIColor blackColor], only used for SVProgressHUDStyleCustom
+ (void)setBackgroundColor:(UIColor*)color; // default is [UIColor whiteColor], only used for SVProgressHUDStyleCustom
+ (void)setBackgroundLayerColor:(UIColor*)color; // default is [UIColor colorWithWhite:0 alpha:0.4], only used for SVProgressHUDMaskTypeCustom
+ (void)setImageViewSize:(CGSize)size; // default is 28x28 pt
+ (void)setInfoImage:(UIImage*)image; // default is the bundled info image provided by Freepik
+ (void)setSuccessImage:(UIImage*)image; // default is bundled success image from Freepik
+ (void)setErrorImage:(UIImage*)image; // default is bundled error image from Freepik
+ (void)setViewForExtension:(UIView*)view; // default is nil, only used if #define SV_APP_EXTENSIONS is set
+ (void)setGraceTimeInterval:(NSTimeInterval)interval; // default is 0 seconds
+ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval; // default is 5.0 seconds
+ (void)setMaximumDismissTimeInterval:(NSTimeInterval)interval; // default is CGFLOAT_MAX
+ (void)setFadeInAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds
+ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds
+ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel; // default is UIWindowLevelNormal
+ (void)setHapticsEnabled:(BOOL)hapticsEnabled; // default is NO
样式
作为标准SVProgressHUD
提供两种预先配置的样式:
SVProgressHUDStyleLight
白色背景黑色图标和文字
SVProgressHUDStyleDark
黑色背景与白色图标和文本
如果要使用自定义颜色使用setForegroundColor
和setBackgroundColor:
。这些方法将HUD的风格置为SVProgressHUDStyleCustom
。
触觉反馈
对于具有较新设备的用户(从iPhone 7开始),SVProgressHUD可以根据显示的HUD来自动触发触觉反馈。反馈图如下:
showSuccessWithStatus: < - > UINotificationFeedbackTypeSuccess
showInfoWithStatus: < - > UINotificationFeedbackTypeWarning
showErrorWithStatus: < - > UINotificationFeedbackTypeError
要启用此功能,请使用setHapticsEnabled:
。
具有iPhone 7之前的设备的用户将不会改变功能。
通知
SVProgressHUD
发布四个通知,NSNotificationCenter
以响应被显示/拒绝:
SVProgressHUDWillAppearNotification 提示框即将出现
SVProgressHUDDidAppearNotification 提示框已经出现
SVProgressHUDWillDisappearNotification 提示框即将消失
SVProgressHUDDidDisappearNotification 提示框已经消失
每个通知通过一个userInfo保存HUD状态字符串(如果有的话)的字典,可以通过检索SVProgressHUDStatusUserInfoKey
。
SVProgressHUD SVProgressHUDDidReceiveTouchEventNotification
当用户触摸整个屏幕或SVProgressHUDDidTouchDownInsideNotification
用户直接触摸HUD时也会发布。由于此通知userInfo
未被传递,而对象参数包含UIEvent
与触摸相关的参数。
应用扩展
这里对这个功能不做详解.自行摸索.
自定义动画
SVProgressHUD提供了方法可以自定义图片.但是不支持gif格式,直接利用下面的方法依然显示一张静态的图片
[SVProgressHUD showImage:[UIImage imageNamed:@"loading.gif"] status:@"加载中..."];
我们可以把gif转化为一个动态的image.
下面是我在百度上搜的一个方法.仅供参考.
#import
typedef void (^GIFimageBlock)(UIImage *GIFImage);
@interface UIImage (GIFImage)
/** 根据本地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;
下面是.m的方法实现.
#import "UIImage+GIFImage.h"
#import
@implementation UIImage (GIFImage)
+ (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 传入图片只有一张 不分@Nx
NSData *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 and
// for more information.
if (frameDuration < 0.011f) {
frameDuration = 0.100f;
}
CFRelease(cfFrameProperties);
return frameDuration;
}
@end
这个是UIimage的分类,在用到的控制器里面调用代码方法即可.这个分类实现我也不太懂.只会用.
_imgView1.image = [UIImage imageWithGIFNamed:@"xuanxuan"];
NSString *path = [[NSBundle mainBundle] pathForResource:@"xuanxuan" ofType:@"gif"];
NSData *imgData = [NSData dataWithContentsOfFile:path];
_imgView2.image = [UIImage imageWithGIFData:imgData];
[UIImage imageWithGIFUrl:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1495708809771&di=da92fc5cf3bdd684711ab5124ee43183&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fw%253D580%2Fsign%3D91bd6cd2d42a60595210e1121835342d%2F212eb9389b504fc215d0301ee6dde71190ef6d1a.jpg" and:^(UIImage *GIFImage) {
_imgView3.image = GIFImage;
}];