造这个轮子的原因
几乎每个app都有loading图,虽然有SVProgressHUD
和MBProgressHUD
这些非常优秀的三方,但我还是觉得要自己会封装才是王道,毕竟:
- 直接拿来的不一定满足需求,尤其是产品迭代较快、需求比较奇葩的时候
- 万一哪天这个三方没人维护了怎么办?还是用自己的踏实
效果演示
效果演示.gif分析loading图
一般说来,loading图就是一个覆盖全屏的自定义view,并且你不可能同时看到两个loading图,所以loading图是单例。用得最多的场景是请求数据的时候展示,请求数据完成就移除。
根据我有限的经验,loading图往往需要满足这个需求:
可控的用户交互。
比如说,用户支付的时候,这个时候我们是不希望用户进行任何操作的。另一种情况,用户跳转到一个新页面,这个页面请求数据展示loading图,loading图挡住了返回按钮,从用户的角度来看,用户是希望可以随时点击返回按钮返回上一页的,而不是只能等着数据加载完成后才能进行操作。(类似于我demo演示的情况)
功能实现
1.文件说明
CQLoadingView
是对loading图的封装;
CQHUD
是对loading图的管理和控制。
2.封装loading图view:CQLoadingView
.h文件
#import <UIKit/UIKit.h>
@interface CQLoadingView : UIView
/** loading信息 */
@property (nonatomic, copy) NSString *loadingInfo;
/** loading图单例 */
+ (instancetype)sharedInstance;
@end
.m文件
#import "CQLoadingView.h"
#import <Masonry.h>
@implementation CQLoadingView{
/** loading信息label */
UILabel *_loadingInfoLabel;
}
static CQLoadingView *loadingView;
#pragma mark - loading图单例
/** loading图单例 */
+ (instancetype)sharedInstance {
if (loadingView == nil) {
loadingView = [[CQLoadingView alloc] init];
}
return loadingView;
}
#pragma mark - 构造方法
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.2];
//------- loading imageView -------//
UIImageView *loadingImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 45, 45)];
[self addSubview:loadingImageView];
loadingImageView.image = [UIImage imageNamed:@"loading_00000"];
NSMutableArray *imageArray = [NSMutableArray array];
for (int i = 0; i < 15; i ++) {
NSString *imageName = [NSString stringWithFormat:@"loading_%05d",i];
[imageArray addObject:[UIImage imageNamed:imageName]];
}
loadingImageView.animationImages = imageArray;
loadingImageView.animationDuration = 0.5;
loadingImageView.animationRepeatCount = 0;
[loadingImageView startAnimating];
[loadingImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self);
make.size.mas_equalTo(CGSizeMake(45, 45));
}];
//------- 说明文本 -------//
_loadingInfoLabel = [[UILabel alloc] init];
[self addSubview:_loadingInfoLabel];
_loadingInfoLabel.textAlignment = NSTextAlignmentCenter;
_loadingInfoLabel.font = [UIFont systemFontOfSize:14];
_loadingInfoLabel.textColor = [UIColor redColor];
[_loadingInfoLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(loadingImageView);
make.top.mas_equalTo(loadingImageView.mas_bottom).mas_offset(20);
make.height.mas_equalTo(18);
}];
}
return self;
}
#pragma mark - 赋值loading说明信息
/** 赋值loading说明信息 */
- (void)setLoadingInfo:(NSString *)loadingInfo{
_loadingInfo = loadingInfo;
_loadingInfoLabel.text = _loadingInfo;
}
@end
封装loading图view很常规,根据产品需求搭建UI即可,建议用自动布局。
3.对loading图的管理和控制:CQHUD
.h文件
#pragma mark - 展示loading图
/** 展示loading图 */
+ (void)showLoading;
#pragma mark - 展示带说明信息的loading图
/**
带说明信息loading图
@param message 说明信息
*/
+ (void)showLoadingWithMessage:(NSString *)message;
#pragma mark - 移除loading图
/** 移除loading图 */
+ (void)dismiss;
#pragma mark - loading期间,允许或禁止用户交互
/**
loading期间,允许或禁止用户交互
@param isEnable YES:允许 NO:禁止
*/
+ (void)enableUserInteraction:(BOOL)isEnable;
#pragma mark - 展示可控制用户交互的loading图
/**
展示可控制用户交互的loading图
@param isEnable 是否允许用户交互
*/
+ (void)showLoadingWithEnableUserInteraction:(BOOL)isEnable;
#pragma mark - 展示可控制用户交互并且带说明信息的loading图
/**
展示可控制用户交互并且带说明信息的loading图
@param message 说明信息
@param isEnable 是否允许用户交互
*/
+ (void)showLoadingWithMessage:(NSString *)message enableUserInteraction:(BOOL)isEnable;
.m文件
#pragma mark - 展示loading图
/** 展示loading图 */
+ (void)showLoading {
[CQHUD showLoadingWithMessage:nil];
}
#pragma mark - 展示带说明信息的loading图
/**
带说明信息loading图
@param message 说明信息
*/
+ (void)showLoadingWithMessage:(NSString *)message {
UIWindow * window = [[[UIApplication sharedApplication] delegate] window];
[window addSubview:[CQLoadingView sharedInstance]];
[CQLoadingView sharedInstance].loadingInfo = message;
[[CQLoadingView sharedInstance] mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(UIEdgeInsetsMake(0, 0, 0, 0));
}];
}
#pragma mark - 移除loading图
/** 移除loading图 */
+ (void)dismiss {
[[CQLoadingView sharedInstance] removeFromSuperview];
}
#pragma mark - loading期间,允许或禁止用户交互
/**
loading期间,允许或禁止用户交互
@param isEnable YES:允许 NO:禁止
*/
+ (void)enableUserInteraction:(BOOL)isEnable {
[CQLoadingView sharedInstance].userInteractionEnabled = !isEnable;
}
#pragma mark - 展示可控制用户交互的loading图
/**
展示可控制用户交互的loading图
@param isEnable 是否允许用户交互
*/
+ (void)showLoadingWithEnableUserInteraction:(BOOL)isEnable {
[CQHUD showLoading];
[CQHUD enableUserInteraction:isEnable];
}
#pragma mark - 展示可控制用户交互并且带说明信息的loading图
/**
展示可控制用户交互并且带说明信息的loading图
@param message 说明信息
@param isEnable 是否允许用户交互
*/
+ (void)showLoadingWithMessage:(NSString *)message enableUserInteraction:(BOOL)isEnable {
[CQHUD showLoadingWithMessage:message];
[CQHUD enableUserInteraction:isEnable];
}
对loading图的管理和控制其实就是对那个单例对象进行处理。
使用
// 展示loading
[CQHUD showLoading];
// 禁止用户交互
[CQHUD enableUserInteraction:NO];
// 展示loading,说明信息:支付中
[CQHUD showLoadingWithMessage:@"支付中"];
// 展示loading并且允许用户交互
[CQHUD showLoadingWithEnableUserInteraction:YES];
// 展示loading提示“支付中”并且禁止用户交互
[CQHUD showLoadingWithMessage:@"支付中" enableUserInteraction:NO];
// 移除loading
[CQHUD dismiss];
demo
最后
暂时还没有研究SVProgressHUD
和MBProgressHUD
的源代码,等我练出6块腹肌就有时间研究了,希望有好心人可以打赏一元让我多买一个鸡蛋早日练出6块腹肌。
网友评论
我是个菜鸟,看到这儿跟别人不一样就问一问