MBProgressHUD1.0.0源码解析
MBProgressHUD是一个显示提示窗口的三方库,常用于用户交互、后台耗时操作等的提示。通过显示一个提示框,通知用户操作或任务的执行状态;同时,利用动画效果,降低用户等待的焦虑心理,增强用户体验。
本篇文章从源码角度来看一下MBProgressHUD是如何实现的,所用的知识都是比较基础的,不过还是值得我们学习一下。详解如下:
1. 类介绍
MBProgressHUD
这是MBProgressHUD的主要类,提供丰富的属性来调整视图的样式。MBRoundProgressView
这是提供Determinate视图显示的类,有非圆环和圆环视图两种方式。MBBarProgressView
这是提供进度条的视图类。MBBackgroundView
这是MBProgressHUD的背景视图类,利用UIVisualEffectView提供毛玻璃效果
2. MBProgressHUD类的显示模式
MBProgressHUDModeIndeterminate

MBProgressHUDModeDeterminate

MBProgressHUDModeDeterminateHorizontalBar

MBProgressHUDModeAnnularDeterminate

MBProgressHUDModeCustomView
这是自定义视图
MBProgressHUDModeText

3.动画模式
MBProgressHUDAnimationFade: 渐变模式MBProgressHUDAnimationZoom: Zoom In & Zoom OutMBProgressHUDAnimationZoomOut: 消失时带变小动画MBProgressHUDAnimationZoomIn: 出现时带变大动画
4. 背景样式
MBProgressHUDBackgroundStyleSolidColor: 正常颜色MBProgressHUDBackgroundStyleBlur: 毛玻璃效果
5. 视图内容
@property (strong, nonatomic, readonly) UILabel *label;: 标题@property (strong, nonatomic, readonly) UILabel *detailsLabel;:详情@property (strong, nonatomic, readonly) UIButton *button: 按钮(显示在标题下方)@property (strong, nonatomic, nullable) UIView *customView;:用户自定义视图@property (strong, nonatomic, readonly) MBBackgroundView *backgroundView;: 整个背景视图@property (strong, nonatomic, readonly) MBBackgroundView *bezelView;:提示框背景视图@property (strong, nonatomic, nullable) UIColor *contentColor UI_APPEARANCE_SELECTOR;: 提示框的内容颜色@property (assign, nonatomic) CGPoint offset UI_APPEARANCE_SELECTOR;:提示框相对父视图中心点的偏移量@property (assign, nonatomic) CGFloat margin UI_APPEARANCE_SELECTOR;:提示框内的内容视图的边距@property (assign, nonatomic) CGSize minSize UI_APPEARANCE_SELECTOR;:提示框最小尺寸@property (assign, nonatomic) BOOL removeFromSuperViewOnHide;:隐藏时从父视图中删除@property (assign, nonatomic) NSTimeInterval graceTime;:延迟多久后显示提示框,避免快速执行的任务也显示提示框,给用户造成视觉干扰。@property (assign, nonatomic) NSTimeInterval minShowTime;:提示框视图最少展示的时间
6. 创建和隐藏视图
- 创建流程
通过+ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated类方法创建视图,也可以通过对象方法创建,不过建议用类方法,不仅创建方便,而且会自动的添加到父视图,然后进行显示。其中,创建过程如下: 
- (void)commonInit {
	// Set default values for properties
	_animationType = MBProgressHUDAnimationFade;
	_mode = MBProgressHUDModeIndeterminate;
	_margin = 20.0f;
	_opacity = 1.f;
	_defaultMotionEffectsEnabled = YES;
	// Default color, depending on the current iOS version
	BOOL isLegacy = kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0;
	_contentColor = isLegacy ? [UIColor whiteColor] : [UIColor colorWithWhite:0.f alpha:0.7f];
	// Transparent background self.opaque = NO;
	self.backgroundColor = [UIColor clearColor];
	// Make it invisible for now self.alpha = 0.0f;
	self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.layer.allowsGroupOpacity = NO;
	[self setupViews]; [self updateIndicators];
	[self registerForNotifications];
}
我们可以发现,通过添加子空间后,根据视图模式调用updateIndicators 方法来创建不同的视图,最后添加了一个状态栏的通知,用来在横竖屏时跳转视图。其中,在显示提示框时,会首先判断graceTime,如过不为0,那么就创建一个定时器倒计时,时间到之后再判断任务是否结束,如果finished 不为空,就开始显示提示框。
- (void)showAnimated:(BOOL)animated {
    MBMainThreadAssert();
    [self.minShowTimer invalidate];
    self.useAnimation = animated;
    self.finished = NO;
    // If the grace time is set, postpone the HUD display
    if (self.graceTime > 0.0) {
        NSTimer *timer = [NSTimer timerWithTimeInterval:self.graceTime target:self selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        self.graceTimer = timer;
    }
    // ... otherwise show the HUD immediately
    else {
        [self showUsingAnimation:self.useAnimation];
    }
}
- (void)handleGraceTimer:(NSTimer *)theTimer
{
	// Show the HUD only if the task is still running
	if (!self.hasFinished) {
		[self showUsingAnimation:self.useAnimation];
	}
}
- 隐藏视图 通过 
+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated隐藏视图,其中会根据minShowTime来判断是否立即隐藏提示框。如果,minShowTime不为0,那么会创建一个定时器,并把定时器加入到common模式的runloop里,等时间到后再把提示框隐藏。 
- (void)hideAnimated:(BOOL)animated
{
	MBMainThreadAssert();
    [self.graceTimer invalidate];
    self.useAnimation = animated;
    self.finished = YES;
    // If the minShow time is set, calculate how long the HUD was shown,
    // and postpone the hiding operation if necessary
    if (self.minShowTime > 0.0 && self.showStarted) {
        NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:self.showStarted];
        if (interv < self.minShowTime) {
            NSTimer *timer = [NSTimer timerWithTimeInterval:(self.minShowTime - interv) target:self selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO];
            [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
            self.minShowTimer = timer;
            return;
        }
    }
    // ... otherwise hide the HUD immediately
    [self hideUsingAnimation:self.useAnimation];
}
7. MBRoundProgressView 和 MBBarProgressView
这两个类,分别创建了 Determinate 和 进度条 的提示框视图,具体实现方法是在 - (void)drawRect:(CGRect)rect 方法里通过 UIBezierPath 或者 Quarts2D 画出,设计思想算是常规,请参考代码细读。
8. MBProgressHUD应用
对于三方框架,使用之前,最好先封装一层(继承或分类),方便以后的调试和新框架替换。封装时,尽量用类方法,使用时比较简洁。
- 添加提示框
 
+ (void)showHUDWithText:(NSString *)text inView:(UIView *)view deley:(NSTimeInterval)time
{
	if (text == nil || text.length <= 0) {
		return;
	}
	if (view == nil) {
		view = [[UIApplication sharedApplication].windows lastObject];
	}
	MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:view animated:YES];
	HUD.mode = MBProgressHUDModeText;
	[HUD hideAnimated:YES afterDelay:1.5];
}
- 隐藏提示框 (改方法调用时,最好在主线程,异步线程可能会出现问题)
 
+ (void)hideHUDForView:(UIView *)view
{
	if (view == nil) view = [[UIApplication sharedApplication].windows lastObject];
	[self hideHUDForView:view animated:YES];
}
参考资料
https://github.com/jdg/MBProgressHUD
MBProgressHUD1.0.0源码解析的更多相关文章
- Masonry1.0.2 源码解析
		
在了解Masonry框架之前,有必要先了解一下自动布局的概念.在iOS6之前,UI布局的方式是通过frame属性和Autoresizing来完成的,而在iOS6之后,苹果公司推出了AutoLayout ...
 - SpringBoot 2.0.3 源码解析
		
前言 用SpringBoot也有很长一段时间了,一直是底层使用者,没有研究过其到底是怎么运行的,借此机会今天试着将源码读一下,在此记录...我这里使用的SpringBoot 版本是 2.0.3.RE ...
 - YYModel V1.0.4源码解析
		
YYKit出现了很长时间了,一直想要详细解析一下它的源码,都是各种缘由推迟了. 最近稍微闲了一点,决定先从最简单的YYModel开始吧. 首先,我也先去搜索了一下YYModel相关的文章,解析主要AP ...
 - 【JUC源码解析】CyclicBarrier
		
简介 CyclicBarrier,一个同步器,允许多个线程相互等待,直到达到一个公共屏障点. 概述 CyclicBarrier支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后 ...
 - Redis系列(十):数据结构Set源码解析和SADD、SINTER、SDIFF、SUNION、SPOP命令
		
1.介绍 Hash是以K->V形式存储,而Set则是K存储,空间节省了很多 Redis中Set是String类型的无序集合:集合成员是唯一的. 这就意味着集合中不能出现重复的数据.可根据应用场景 ...
 - ArrayList、CopyOnWriteArrayList源码解析(JDK1.8)
		
本篇文章主要是学习后的知识记录,存在不足,或许不够深入,还请谅解. 目录 ArrayList源码解析 ArrayList中的变量 ArrayList构造函数 ArrayList中的add方法 Arra ...
 - EventBus3.0源码解析
		
本文主要介绍EventBus3.0的源码 EventBus是一个Android事件发布/订阅框架,通过解耦发布者和订阅者简化 Android 事件传递. EventBus使用简单,并将事件发布和订阅充 ...
 - solr&lucene3.6.0源码解析(四)
		
本文要描述的是solr的查询插件,该查询插件目的用于生成Lucene的查询Query,类似于查询条件表达式,与solr查询插件相关UML类图如下: 如果我们强行将上面的类图纳入某种设计模式语言的话,本 ...
 - solr&lucene3.6.0源码解析(三)
		
solr索引操作(包括新增 更新 删除 提交 合并等)相关UML图如下 从上面的类图我们可以发现,其中体现了工厂方法模式及责任链模式的运用 UpdateRequestProcessor相当于责任链模式 ...
 - Heritrix 3.1.0 源码解析(三十七)
		
今天有兴趣重新看了一下heritrix3.1.0系统里面的线程池源码,heritrix系统没有采用java的cocurrency包里面的并发框架,而是采用了线程组ThreadGroup类来实现线程池的 ...
 
随机推荐
- Hibernate快速入门实例
			
Hibernate工程项目创建基本步骤:导包(Hibernate依赖包.SQL驱动包).编写实体类.编写ORM映射配置文件.编写核心配置文件.编写测试驱动. 整个工程项目结构如下图: 一.导包 笔者使 ...
 - How to install MySQL on CentOS
			
1)chekc centos中是否安装了MySQL [root@localhost MySQL]# rpm -qa | grep mariadb mariadb-libs-5.5.52-1.el7.x ...
 - git命令小结
			
注: 如果你使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文 学习git文档推荐:http://www.liaoxuefeng.com/wiki/00137 ...
 - js几秒以后倒计时跳转示例
			
代码如下: <html> <head> <title>出错啦~~~</title> <link href="css/login1.css ...
 - Java条形码/二维码生成和解析
			
注意-本类依赖jar包文件:core.jar和zxing-javase.jar 下载jar文件,到本博客文件栏目下载. import com.google.zxing.BarcodeFormat; i ...
 - DDD理论学习系列(11)-- 工厂
			
DDD理论学习系列--案例及目录 1.引言 在针对大型的复杂领域进行建模时,聚合.实体和值对象之间的依赖关系可能会变得十分复杂.在某个对象中为了确保其依赖对象的有效实例被创建,需要深入了解对象实例化逻 ...
 - 关于tomcat下startup.bat双击闪退的问题
			
背景:之前做单点登录,复制了几个tomcat,改了各自端口,当做不同服务器用. 今天无意间随便点击了一个tomcat下的startup.bat批处理文件,结果出来控制台,没出几行信息就闪退了.点击其他 ...
 - 安卓平台使用pocketSphinx离线语音识别
			
版权声明:本文为elecdog原创文章,可以转载,但必须在明确位置注明出处!谢谢合作. 关于语音识别,国内已经有比较好的公司推出相关的服务了,比如百度免费的离在线融合语音识别以及讯飞收费的在线和离线语 ...
 - PHP删除文件夹及其文件
			
<?php function deletedir($path){ $openpath = opendir($path); while ($f = readdir($openpath)){ $fi ...
 - NLP —— 图模型(零):EM算法简述及简单示例(三硬币模型)
			
最近接触了pLSA模型,该模型需要使用期望最大化(Expectation Maximization)算法求解. 本文简述了以下内容: 为什么需要EM算法 EM算法的推导与流程 EM算法的收敛性定理 使 ...