ProgressHUD源碼詳解
ProgressHUD是iOS開發(fā)中常用的等待控件(菊花控件)帽氓,用戶網(wǎng)絡(luò)請(qǐng)求等
主要結(jié)構(gòu)
ProgressHUD
只包含兩個(gè)代碼文件ProgressHUD.h
和ProgressHUD.m
杠纵,以及一個(gè)資源文件ProgressHUD.bundle
ProgressHUD
本質(zhì)上為UIView
的子類
@interface ProgressHUD : UIView
其主要結(jié)構(gòu)包含5部分:
@interface ProgressHUD()
{
UIWindow *window;
UIView *viewBackground;
UIToolbar *toolbarHUD;
UIActivityIndicatorView *spinner;
UIImageView *imageView;
UILabel *labelStatus;
}
以上控件之間的結(jié)構(gòu)關(guān)系如下:
初始化控件
- 在
show
方法中調(diào)用
+ (void)show
{
dispatch_async(dispatch_get_main_queue(), ^{
[[self shared] hudCreate:nil image:nil spin:YES hide:NO interaction:YES];
});
}
- 初始化
- (void)hudCreate:(NSString *)status image:(UIImage *)image spin:(BOOL)spin hide:(BOOL)hide interaction:(BOOL)interaction
{
//初始化toolbarHUD
if (toolbarHUD == nil)
{
toolbarHUD = [[UIToolbar alloc] initWithFrame:CGRectZero];
toolbarHUD.translucent = YES;
toolbarHUD.backgroundColor = self.hudColor;
toolbarHUD.layer.cornerRadius = 10;
toolbarHUD.layer.masksToBounds = YES;
[self registerNotifications];
}
if (toolbarHUD.superview == nil)
{
//如果與背景視圖不可交互克蚂,初始化背景視圖逢捺,背景視圖為toolbarHUD的父視圖
if (interaction == NO)
{
viewBackground = [[UIView alloc] initWithFrame:window.frame];
viewBackground.backgroundColor = self.backgroundColor;
[window addSubview:viewBackground];
[viewBackground addSubview:toolbarHUD];
}//如果與背景視圖可交互,頂層window為toolbarHUD的父視圖
else [window addSubview:toolbarHUD];
}
//初始化spinner(菊花),并添加到toolbarHUD
if (spinner == nil)
{
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.color = self.spinnerColor;
spinner.hidesWhenStopped = YES;
}
if (spinner.superview == nil) [toolbarHUD addSubview:spinner];
//初始化imageView并添加到toolbarHUD
if (imageView == nil)
{
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 28, 28)];
}
if (imageView.superview == nil) [toolbarHUD addSubview:imageView];
//初始化labelStatus魏宽,添加到toolbarHUD
if (labelStatus == nil)
{
labelStatus = [[UILabel alloc] initWithFrame:CGRectZero];
labelStatus.font = self.statusFont;
labelStatus.textColor = self.statusColor;
labelStatus.backgroundColor = [UIColor clearColor];
labelStatus.textAlignment = NSTextAlignmentCenter;
labelStatus.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
labelStatus.numberOfLines = 0;
}
if (labelStatus.superview == nil) [toolbarHUD addSubview:labelStatus];
//文本信息添加
labelStatus.text = status;
labelStatus.hidden = (status == nil) ? YES : NO;
//圖片信息添加
imageView.image = image;
imageView.hidden = (image == nil) ? YES : NO;
//spinner(菊花)旋轉(zhuǎn)(或停止)
if (spin) [spinner startAnimating]; else [spinner stopAnimating];
[self hudSize];//尺寸設(shè)置
[self hudPosition:nil];//位置設(shè)置
[self hudShow];//動(dòng)畫顯示
//定時(shí)關(guān)閉
if (hide) [self timedHide];
}
設(shè)置Size
- (void)hudSize
{
CGRect rectLabel = CGRectZero;
CGFloat widthHUD = 100, heightHUD = 100;//toolbarHUD默認(rèn)的尺寸
if (labelStatus.text != nil)
{
NSDictionary *attributes = @{NSFontAttributeName:labelStatus.font};
NSInteger options = NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin;
rectLabel = [labelStatus.text boundingRectWithSize:CGSizeMake(200, 300) options:options attributes:attributes context:NULL];//計(jì)算文字所需的Rect
//toolbarHUD對(duì)應(yīng)的Rect
widthHUD = rectLabel.size.width + 50;
heightHUD = rectLabel.size.height + 75;
if (widthHUD < 100) widthHUD = 100;
if (heightHUD < 100) heightHUD = 100;
rectLabel.origin.x = (widthHUD - rectLabel.size.width) / 2;
rectLabel.origin.y = (heightHUD - rectLabel.size.height) / 2 + 25;
}
toolbarHUD.bounds = CGRectMake(0, 0, widthHUD, heightHUD);
//imageView對(duì)應(yīng)的位置
CGFloat imageX = widthHUD/2;
CGFloat imageY = (labelStatus.text == nil) ? heightHUD/2 : 36;
imageView.center = spinner.center = CGPointMake(imageX, imageY);
labelStatus.frame = rectLabel;
}
設(shè)置postion
- (void)hudPosition:(NSNotification *)notification
{
CGFloat heightKeyboard = 0;
NSTimeInterval duration = 0;
//計(jì)算鍵盤高度
if (notification != nil)
{
NSDictionary *info = [notification userInfo];
CGRect keyboard = [[info valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
duration = [[info valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
if ((notification.name == UIKeyboardWillShowNotification) || (notification.name == UIKeyboardDidShowNotification))
{
heightKeyboard = keyboard.size.height;
}
}
else heightKeyboard = [self keyboardHeight];
//toolbarHUD的水平中心在屏幕中間萨螺,垂直中心在除去鍵盤高度的中心。
CGRect screen = [UIScreen mainScreen].bounds;
CGPoint center = CGPointMake(screen.size.width/2, (screen.size.height-heightKeyboard)/2);
//動(dòng)態(tài)設(shè)置toolbarHUD的中心
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
self->toolbarHUD.center = CGPointMake(center.x, center.y);
} completion:nil];
if (viewBackground != nil) viewBackground.frame = window.frame;
}
- 注意:
-
toolbarHUD
的水平中心在屏幕中間吃衅,垂直中心在除去鍵盤高度的中心跳仿。
CGPoint center = CGPointMake(screen.size.width/2, (screen.size.height-heightKeyboard)/2);
-
toolbarHUD
的垂直中心會(huì)根據(jù)鍵盤消息進(jìn)行調(diào)整。
顯示
- (void)hudShow
{
if (self.alpha == 0)
{
self.alpha = 1;
toolbarHUD.alpha = 0; //初始設(shè)置為完全透明捐晶,實(shí)現(xiàn)隱藏功能
toolbarHUD.transform = CGAffineTransformScale(toolbarHUD.transform, 1.4, 1.4); //放大
UIViewAnimationOptions options = UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseOut; //動(dòng)畫模式設(shè)置
//動(dòng)畫顯示
[UIView animateWithDuration:0.15 delay:0 options:options animations:^{
self->toolbarHUD.transform = CGAffineTransformScale(self->toolbarHUD.transform, 1/1.4, 1/1.4); //恢復(fù)正常
self->toolbarHUD.alpha = 1; //設(shè)為不透明菲语,顯示出來(lái)
} completion:nil];
}
}
隱藏
- (void)hudHide
{
if (self.alpha == 1)
{
UIViewAnimationOptions options = UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseIn; //動(dòng)畫模式設(shè)置
[UIView animateWithDuration:0.15 delay:0 options:options animations:^{
self->toolbarHUD.transform = CGAffineTransformScale(self->toolbarHUD.transform, 0.7, 0.7); //縮小為原來(lái)的0.7倍
self->toolbarHUD.alpha = 0; //設(shè)置為透明,實(shí)現(xiàn)隱藏
}
completion:^(BOOL finished) {
[self hudDestroy]; //刪除各控件的依賴關(guān)系惑灵,再刪除控件
self.alpha = 0;
}];
}
}