需求如下:

屏幕快照 2018-09-17 下午2.41.31.png
在每個項目中,都會在請求數(shù)據(jù)為空或者網(wǎng)絡(luò)不好的時候,提示用戶當(dāng)前網(wǎng)絡(luò)狀態(tài)的占位圖。已達(dá)到效果和美觀上都給人比較好的提示。以前都是針對不同場景展示不同的站位圖片,每個用到的地方,都要自己寫一遍空視圖。由于該項目中用到的地方比較多,所以封裝了出來。使用者,直接傳入想對應(yīng)頁面的占位圖枚舉參數(shù)即可。不需要增加太多的代碼。
思路:
第一種:空視圖無非就是一個View 和一個用于展示文案的UILabel。
第二種:空視圖還可以展示一個view+一個用于刷新試圖的UIButton 按鈕。
·首先我們需要封裝一個無數(shù)據(jù)占位圖
一個項目中,無數(shù)據(jù)占位圖不光只有一種,但是可以看到他們的布局是非常相似的,所以我的做法是根據(jù)不同的值,創(chuàng)建不同的UI。
首先先要定一個一個枚舉
typedef enum{
TimeOutEmptyType = 0, // 網(wǎng)絡(luò)請求超時
NoneSearchDataEmptyType, // 暫無搜索結(jié)果
NoneDataEmptyType, // 暫無數(shù)據(jù)
ErrorEmptyType, // 頁面出錯啦~
LocationErrorEmptyType, // 無法獲取位置信息
NoNetWorkEmptyType, // 網(wǎng)絡(luò)無法連接
NoShopAssitantType, // 沒有店鋪助理
NoInspectionTemplateType, // 沒有巡檢模版
NoInspectionTaskType, // 沒有巡檢任務(wù)
NOOpenDoorDataType, // 沒有開門數(shù)據(jù)
NoneVisitorType, // 沒有拜訪者數(shù)據(jù)
NORepairRecordDataType, // 沒有維修記錄
NOEMRecordDataType, // 沒有保養(yǎng)記錄
NoBlueToothDoor, // 沒有附近的門
NoDeviceSelect, // 沒有選擇設(shè)備
NoNoticeType, // 沒有通知記錄
NoAnnounceType, // 沒有公告記錄
NoPaymentType, // 沒有收費(fèi)記錄
NoTicketType // 沒有工單待辦記錄
}EmptyType;
當(dāng)然這肯定不是項目中全部的空視圖,它會根據(jù)業(yè)務(wù)需求不斷的增加。
.h
@interface SCEmptyView : UIView
@property (nonatomic, strong) UIImageView *emptyImage;
@property (nonatomic, strong) UILabel *titleLab;
@property (nonatomic, strong) UILabel *subTitleLab;
@property (nonatomic, strong) UIButton* retryBtn;
提供兩個類方法,用于直接創(chuàng)建空視圖。
+ (SCEmptyView*)defaultEmptyView;
+ (SCEmptyView*)emptyViewWithImage:(UIImage*)img title:(NSString*)title subTitle:(NSString*)subTitle;
初始化空界面,返回自定義空數(shù)據(jù)View
/*!
* @author wyy
*
* @brief 初始化空界面
*
* @param icon 圖標(biāo)
* @param title 標(biāo)題
* @param subTitle 副標(biāo)題
* @param btnTitle 按鈕文字
*
* @return 返回自定義空數(shù)據(jù)View
*/
- (SCEmptyView*)initWithFrame:(CGRect)frame icon:(NSString*)icon title:(NSString*)title subTitle:(NSString*)subTitle buttonTitle:(NSString *)btnTitle;
根據(jù)空數(shù)據(jù)原因類型獲取空界面,返回空數(shù)據(jù)View
+ (SCEmptyView*)emptyViewWithType:(EmptyType)emptyType frame:(CGRect)frame;
ok 那就來看一下具體實現(xiàn)吧。.m
@implementation SCEmptyView
- (UIView *)initWithIcon:(NSString *)icon Title:(NSString *)title ButtonTitle:(NSString *)btnTitle OtherTitles:(NSArray *)titles
{
if (self = [self init]) {
self.frame = CGRectMake(0, 0, kSCREEN_WIDTH, kSCREEN_HEIGHT);
self.tag = 65535;
CGFloat wh = 130;
UIImageView *imgView=[[UIImageView alloc] initWithFrame:CGRectMake(kSCREEN_WIDTH*0.5-wh*0.5, 85, wh, wh)];
if (icon != nil && ![icon isEqualToString:@""]) {
[imgView setImage:[UIImage imageNamed:icon]];
}
[self addSubview:imgView];
UILabel *textLabel=[[UILabel alloc] initWithFrame:CGRectMake(15, CGRectGetMaxY(imgView.frame) + 10, kSCREEN_WIDTH - 2*15, 18)];
textLabel.textAlignment=NSTextAlignmentCenter;
textLabel.textColor = [UIColor blackColor];
textLabel.font = [UIFont systemFontOfSize:17];
textLabel.numberOfLines = 0;
textLabel.text = title;
[textLabel sizeToFit];
textLabel.center = CGPointMake(self.center.x, textLabel.center.y);
[self addSubview:textLabel];
if (titles.count > 0) {
for (NSString *titleStr in titles) {
textLabel=[[UILabel alloc] initWithFrame:CGRectMake(15, CGRectGetMaxY(textLabel.frame)+10 , kSCREEN_WIDTH - 2*15, 15)];
textLabel.textAlignment=NSTextAlignmentCenter;
textLabel.textColor = [UIColor blackColor];
textLabel.font=[UIFont systemFontOfSize:14];
textLabel.text = titleStr;
textLabel.numberOfLines = 0;
[textLabel sizeToFit];
textLabel.center = CGPointMake(self.center.x, textLabel.center.y);
[self addSubview:textLabel];
}
}
if (btnTitle != nil && ![btnTitle isEqualToString:@""]) {
UIButton *addNewBtn = [[UIButton alloc] initWithFrame:CGRectMake(kSCREEN_WIDTH*0.5-60, CGRectGetMaxY(textLabel.frame) + 5, 120, 38)];
[addNewBtn setTitle:btnTitle forState:UIControlStateNormal];
[addNewBtn setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
addNewBtn.titleLabel.font = [UIFont systemFontOfSize:17];
[addNewBtn addTarget:self action:@selector(btnClicked) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:addNewBtn];
}
self.backgroundColor = [UIColor SCBackGroundColor];
}
return self;
}
初始化
- (id)init {
self = [super init];
if (self) {
[self initViews];
}
return self;
}
- (void)initViews {
_emptyImage = [[UIImageView alloc] init];
[self addSubview:_emptyImage];
_titleLab = [[UILabel alloc] init];
_titleLab.textAlignment = NSTextAlignmentCenter;
_titleLab.textColor = COLOR(124,121,122,1);
_titleLab.font = [UIFont systemFontOfSize:17];
[self addSubview:_titleLab];
_subTitleLab = [[UILabel alloc] init];
_subTitleLab.textAlignment = NSTextAlignmentCenter;
_subTitleLab.textColor = [UIColor greenColor];
_subTitleLab.font = [UIFont systemFontOfSize:14];
[self addSubview:_subTitleLab];
[_emptyImage mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.mas_centerX);
make.top.equalTo(self.mas_top).with.offset(85);
make.width.mas_equalTo(130);
make.height.mas_equalTo(130);
}];
[_titleLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(_emptyImage.mas_bottom).with.offset(10);
make.left.equalTo(self.mas_left).with.offset(15);
make.right.equalTo(self.mas_right).with.offset(-15);
make.height.mas_equalTo(18);
}];
[_subTitleLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(_titleLab.mas_bottom).with.offset(10);
make.left.equalTo(self.mas_left).with.offset(15);
make.right.equalTo(self.mas_right).with.offset(-15);
make.height.mas_equalTo(15);
}];
}
默認(rèn)的空視圖
+ (SCEmptyView*)defaultEmptyView {
if ([[SCAppInitialize shareInstance] checkNetStatus] ==AFNetworkReachabilityStatusReachableViaWiFi || [[SCAppInitialize shareInstance] checkNetStatus] ==AFNetworkReachabilityStatusReachableViaWWAN || [[SCAppInitialize shareInstance] checkNetStatus] ==AFNetworkReachabilityStatusUnknown) {
return [[SCEmptyView alloc] initWithIcon:@"ic_no_ticket" Title:@"暫無數(shù)據(jù)" ButtonTitle:nil OtherTitles:nil];
}else{
//無網(wǎng)絡(luò)
return [[SCEmptyView alloc] initWithIcon:@"" Title:@"網(wǎng)絡(luò)無法連接" ButtonTitle:@"重試" OtherTitles:[NSArray arrayWithObjects:@"請檢查你的手機(jī)是否連聯(lián)網(wǎng)", nil]];
}
}
+ (SCEmptyView*)emptyViewWithImage:(UIImage*)img title:(NSString*)title subTitle:(NSString*)subTitle {
SCEmptyView *emptyView = [[SCEmptyView alloc] init];
emptyView.emptyImage.image = img;
emptyView.titleLab.text = title;
emptyView.subTitleLab.text = subTitle;
return emptyView;
}
- (SCEmptyView*)initWithFrame:(CGRect)frame icon:(NSString*)icon title:(NSString*)title subTitle:(NSString*)subTitle buttonTitle:(NSString *)btnTitle;{
self = [super initWithFrame:frame];
if (self) {
//空圖標(biāo)
_emptyImage = [[UIImageView alloc] initWithFrame:CGRectMake((self.width-130)/2, 75, 130, 130)];
_emptyImage.image = [UIImage imageNamed:icon];
_emptyImage.contentMode = UIViewContentModeScaleAspectFit;
[self addSubview:_emptyImage];
//顯示標(biāo)題
_titleLab = [[UILabel alloc] initWithFrame:CGRectMake(15, _emptyImage.bottom+10, self.width-2*15, 22)];
_titleLab.textAlignment = NSTextAlignmentCenter;
_titleLab.textColor = [UIColor blackColor];
_titleLab.font = [UIFont systemFontOfSize:16];
_titleLab.text = title;
[self addSubview:_titleLab];
//重試按鈕的頂部位置
CGFloat top = _titleLab.bottom;
//顯示副標(biāo)題
_subTitleLab = [[UILabel alloc] initWithFrame:CGRectMake(15, _titleLab.bottom+10, self.width-2*15, 0)];
_subTitleLab.textAlignment = NSTextAlignmentCenter;
_subTitleLab.textColor = [UIColor blackColor];
_subTitleLab.font = [UIFont systemFontOfSize:12];
[self addSubview:_subTitleLab];
if (subTitle.length > 0) {
_subTitleLab.text = subTitle;
_subTitleLab.height = 16;
top = _subTitleLab.bottom;
}
//重試按鈕
_retryBtn = [UIButton buttonWithType:UIButtonTypeSystem];
_retryBtn.frame = CGRectMake((self.width-100)/2, top+15, 118, 30);
[_retryBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[_retryBtn setBackgroundColor:[UIColor SCBlueColor]];
_retryBtn.titleLabel.font = [UIFont systemFontOfSize:13];
[_retryBtn addTarget:self action:@selector(btnClicked) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_retryBtn];
if (btnTitle.length > 0) {
[_retryBtn setTitle:btnTitle forState:UIControlStateNormal];
}else{
_retryBtn.hidden = YES;
}
}
return self;
}
一般我都會采用下面的方法來創(chuàng)建空視圖
+ (SCEmptyView*)emptyViewWithType:(EmptyType)emptyType frame:(CGRect)frame{
if (emptyType == NoneDataEmptyType) {
return [[SCEmptyView alloc] initWithFrame:frame icon:@"ic_no_ticket" title:@"您還沒有工單哦" subTitle:@"" buttonTitle:@"返回"];
}else if (emptyType == ErrorEmptyType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"" title:@"頁面出錯啦~" subTitle:@"" buttonTitle:@""];
}else if (emptyType == NoNetWorkEmptyType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"" title:@"網(wǎng)絡(luò)無法連接" subTitle:@"請檢查你的手機(jī)是否聯(lián)網(wǎng)" buttonTitle:@"重試"];
}else if (emptyType == TimeOutEmptyType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"" title:@"網(wǎng)絡(luò)請求超時" subTitle:@"" buttonTitle:@"重試"];
}else if (emptyType == NoneSearchDataEmptyType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"" title:@"暫無搜索結(jié)果" subTitle:@"" buttonTitle:@""];
}else if (emptyType == LocationErrorEmptyType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"" title:@"無法獲取位置信息" subTitle:@"" buttonTitle:@"重試"];
}else if(emptyType == NoInspectionTemplateType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"scInspectionEmptyIcon" title:@"" subTitle:@"目前暫無可以選擇的設(shè)備及對應(yīng)的巡檢模板" buttonTitle:@""];
}else if(emptyType == NoInspectionTaskType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"scInspectionEmptyTaskIcon" title:@"" subTitle:@"你還沒有巡檢任務(wù)" buttonTitle:@""];
}else if(emptyType == NOOpenDoorDataType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"zanwumen" title:@"" subTitle:@"暫無您可通行的門" buttonTitle:@""];
}else if(emptyType == NORepairRecordDataType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"NORepairRecordImage" title:@"" subTitle:@"暫無維修記錄" buttonTitle:@""];
}else if(emptyType == NoBlueToothDoor){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"bluetooth" title:@"暫無附近的門" subTitle:@"" buttonTitle:@""];
}else if(emptyType == NOEMRecordDataType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"NOEMRecordImage" title:@"" subTitle:@"暫無保養(yǎng)記錄" buttonTitle:@""];
}else if(emptyType == NoDeviceSelect){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"sc_noDevices" title:@"目前暫無設(shè)備" subTitle:@"" buttonTitle:@""];
}else if(emptyType == NoNoticeType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"NOEMRecordImage" title:@"暫無通知數(shù)據(jù)" subTitle:@"" buttonTitle:@""];
}else if(emptyType == NoAnnounceType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"NOEMRecordImage" title:@"暫無公告數(shù)據(jù)" subTitle:@"" buttonTitle:@""];
}else if(emptyType == NoPaymentType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"NOEMRecordImage" title:@"暫無收費(fèi)數(shù)據(jù)" subTitle:@"" buttonTitle:@""];
}else if(emptyType == NoTicketType){
return [[SCEmptyView alloc] initWithFrame:frame icon:@"NOEMRecordImage" title:@"暫無工單待辦數(shù)據(jù)" subTitle:@"" buttonTitle:@""];
}
return nil;
}
- (void)btnClicked
{
if (_btnClick != nil) {
self.btnClick();
}
}
具體VC中加載空視圖的使用方式如下:
-(SCEmptyView *)emptyView{
if (!_emptyView) {
_emptyView = [SCEmptyView emptyViewWithType:NoNoticeType frame:self.view.frame];
}
return _emptyView;
}
比如我在Tabelview上面加載一個空視圖,就可以用上面的方式加載View。然后根據(jù)數(shù)據(jù)來管理是否隱藏和展示。
[self.tableView setBackgroundView:self.interactor.dataArrayM.count?[UIView new]:self.emptyView];
或者
第一步:
#pragma mark lazy loading
-(SCEmptyView *)emptyView{
if(!_emptyView){
_emptyView = [SCEmptyView emptyViewWithType:NoInspectionTaskType frame:CGRectMake(0, 50, kSCREEN_WIDTH, kSCREEN_HEIGHT)];
_emptyView.hidden = YES;
}
return _emptyView;
}
第二步:
[self.view addSubview:self.emptyView];
第三步:
self.emptyView.hidden = self.interactor.dataArrayM.count?YES:NO;
以上就是針對項目中常用到的占位圖做了一個簡單的封裝。