LQAbnormalView.h文件
//
// LQAbnormalView.h
// test
//
// Created by starxin on 2019/5/30.
// Copyright © 2019 starxin. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/**
异常界面事件回调
@param idx -1:触摸回调,必须设置allowTouchCallback=YES,其它按照按钮的从左到右的顺序从0递增
*/
typedef void (^LQAbnormalEventBlock)(NSInteger idx);
///异常控件:比如数据请求失败空白页面、无权限异常页面等。
///内部控件排序从上到下:图片、文本、子文本、按钮,若都没有则整个控件高度为0
///所有的文本都是居中显示,文本以及子文本的marginLeftXText,marginRightXText,marginLeftXSubText,marginRightXSubText仅用于计算最大的宽度
@interface LQAbnormalView : UIView
#pragma mark --- 图片属性设置
///图片名称,以图片有二进制数据为创建图片控件的依据
@property (nonatomic, copy, readwrite) NSString* imgName;
///图片宽度,默认值图片的实际宽度
@property (nonatomic, assign, readwrite) CGFloat imgWidth;
///图片高度,默认值图片的实际高度
@property (nonatomic, assign, readwrite) CGFloat imgHeight;
///图片显示模式,默认UIViewContentModeScaleAspectFit
@property (nonatomic, assign, readwrite) UIViewContentMode imgContentMode;
///图片的背景颜色,默认是无色
@property (nonatomic, strong, readwrite) UIColor* imgBackgroundColor;
#pragma mark --- 文本内容属性设置
///文本内容,若同时设置了富文本,则富文本优先级高,富文本下文本内容的其他属性设置无效,不为空才会创建文本控件
@property (nonatomic, copy, readwrite) NSString* text;
///文本富文本,不为空才会创建文本控件
@property (nonatomic, copy, readwrite) NSAttributedString* attText;
///文本字体大小,默认系统16
@property (nonatomic, strong, readwrite) UIFont* textFont;
///文本颜色,默认系统darkTextColor
@property (nonatomic, strong, readwrite) UIColor* textColor;
///文本的背景颜色
@property (nonatomic, strong, readwrite) UIColor* textBackgroundColor;
///子文本内容,若同时设置了富文本,则富文本优先级高,富文本下文本内容的其他属性设置无效,不为空才会创建子文本控件
@property (nonatomic, copy, readwrite) NSString* subText;
///子文本富文本,不为空才会创建子文本控件
@property (nonatomic, copy, readwrite) NSAttributedString* subAttText;
///子文本字体大小,默认系统15
@property (nonatomic, strong, readwrite) UIFont* subTextFont;
///子文本颜色默认系统lightTextColor
@property (nonatomic, strong, readwrite) UIColor* subTextColor;
///子文本的背景颜色
@property (nonatomic, strong, readwrite) UIColor* subTextBackgroundColor;
#pragma mark --- 按钮属性设置,注意按钮的宽度是根据间距和父控件宽度动态计算的
///按钮的标题数组,数组个数不等于0才会创建按钮控件
@property (nonatomic, strong, readwrite) NSArray<NSString*>* btnTitlesArr;
///按钮的标题颜色,默认0x222222
@property (nonatomic, strong, readwrite) NSArray<UIColor*>* btnColorsArr;
///按钮的标题字体大小,默认系统15
@property (nonatomic, strong, readwrite) NSArray<UIFont*>* btnFontsArr;
///按钮的border宽度
@property (nonatomic, strong, readwrite) NSArray<NSNumber*>* btnBorderWidthArr;
///按钮的border颜色
@property (nonatomic, strong, readwrite) NSArray<UIColor*>* btnBorderColorArr;
///按钮的corner radius
@property (nonatomic, strong, readwrite) NSArray<NSNumber*>* btnCornerRadiusArr;
///按钮高度,默认是44
@property (nonatomic, assign, readwrite) CGFloat btnHeight;
///按钮背景颜色
@property (nonatomic, strong, readwrite) NSArray<UIColor*>* btnBackgroundColorsArr;
#pragma mark --- 间距设置
///图片和文本垂直方向的间距,默认值为20
@property (nonatomic, assign, readwrite) CGFloat marginBetweenImageAndText;
///文本和子文本垂直方向的间距,默认值为20
@property (nonatomic, assign, readwrite) CGFloat marginBetweenTextAndSubText;
///子文本和按钮垂直方向的间距,默认值为20
@property (nonatomic, assign, readwrite) CGFloat marginBetweenSubTextAndButton;
///文本距离父控件左边距,默认值为20
@property (nonatomic, assign, readwrite) CGFloat marginLeftXText;
///文本距离父控件右边距,默认值为40
@property (nonatomic, assign, readwrite) CGFloat marginRightXText;
///子文本距离父控件左边距,默认值为40
@property (nonatomic, assign, readwrite) CGFloat marginLeftXSubText;
///子文本距离父控件右边距,默认值为40
@property (nonatomic, assign, readwrite) CGFloat marginRightXSubText;
///最左边按钮距离父控件左边距,默认值为40
@property (nonatomic, assign, readwrite) CGFloat marginLeftXLeftButton;
///最右边按钮距离父控件右边距,默认值为40
@property (nonatomic, assign, readwrite) CGFloat marginRightXRightButton;
///按钮之间的间距,默认是20
@property (nonatomic, assign, readwrite) CGFloat marginBetweenButtons;
#pragma mark --- 回调设置
///是否允许触摸回调,默认是NO
@property (nonatomic, assign, getter=isAllowTouchCallback) BOOL allowTouchCallback;
///按钮回调
@property (nonatomic, copy) LQAbnormalEventBlock abnormalEventBlock;
@end
NS_ASSUME_NONNULL_END
LQAbnormalView.m文件
//
// LQAbnormalView.m
// test
//
// Created by 刘欣 on 2019/5/30.
// Copyright © 2019 starxin. All rights reserved.
//
#import "LQAbnormalView.h"
#define kLQHexColor(c) [UIColor colorWithRed:((c>>16)&0xFF)/255.0f green:((c>>8)&0xFF)/255.0f blue:(c&0xFF)/255.0f alpha:1.0f]
@interface LQAbnormalView ()
@property (nonatomic, strong, readonly) UIImageView* iconImgView;
@property (nonatomic, strong, readonly) UILabel* textLbl;
@property (nonatomic, strong, readonly) UILabel* subTextLbl;
@property (nonatomic, strong, readonly) NSMutableArray<UIButton*>* buttonArrM;
///父控件
@property (nonatomic, weak, readonly) UIView* parentView;
@end
@implementation LQAbnormalView
#pragma mark --- life cycle
- (instancetype)init {
if (self = [super init]) {
[self p_initConfiguration];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self p_initConfiguration];
}
return self;
}
- (void)p_initConfiguration {
_imgContentMode = UIViewContentModeScaleAspectFit;
_imgBackgroundColor = UIColor.clearColor;
_textFont = [UIFont systemFontOfSize:16];
_textColor = UIColor.darkTextColor;
_subTextFont = [UIFont systemFontOfSize:15];
_subTextColor = UIColor.lightTextColor;
_btnHeight = 44;
_marginBetweenImageAndText = 20;
_marginBetweenTextAndSubText = 20;
_marginBetweenSubTextAndButton = 20;
_marginLeftXText = 20;
_marginRightXText = 40;
_marginLeftXSubText = 40;
_marginRightXSubText = 40;
_marginLeftXLeftButton = 40;
_marginRightXRightButton = 40;
_marginBetweenButtons = 20;
_buttonArrM = [NSMutableArray array];
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(p_actionForTapGesture)];
[self addGestureRecognizer:tap];
}
- (void)willMoveToSuperview:(UIView *)newSuperview {
// NSLog(@"newSuperview=%@", newSuperview);
_parentView = newSuperview;
[self p_setupView];
}
- (void)p_setupView {
_iconImgView = UIImageView.alloc.init;
_iconImgView.backgroundColor = _imgBackgroundColor;
_textLbl = UILabel.alloc.init;
_textLbl.numberOfLines = 0;
_textLbl.textAlignment = NSTextAlignmentCenter;
_textLbl.preferredMaxLayoutWidth = _parentView.frame.size.width-_marginLeftXText-_marginRightXText;
_subTextLbl = UILabel.alloc.init;
_subTextLbl.textAlignment = NSTextAlignmentCenter;
_subTextLbl.numberOfLines = 0;
_subTextLbl.preferredMaxLayoutWidth = _parentView.frame.size.width-_marginLeftXSubText-_marginRightXSubText;
[self addSubview:self.iconImgView];
[self addSubview:self.textLbl];
[self addSubview:self.subTextLbl];
//图片处理
[self p_actionForInitIconImageView];
//文本处理
[self p_actionForInitTextLabel];
//子文本处理
[self p_actionForInitSubTextLabel];
//按钮处理
[self p_actionForInitButtons];
//计算所有控件的有效高度
[self p_actionForUpdateOrigin];
}
#pragma mark --- actions
///图片处理,主要是设置图片的宽高
- (void)p_actionForInitIconImageView {
if (_imgName) {
UIImage* img = [UIImage imageNamed:_imgName];
if (img) {
if (_imgWidth < 1) {
_imgWidth = img.size.width;
}
if (_imgHeight < 1) {
_imgHeight = img.size.height;
}
_iconImgView.frame = CGRectMake(0, 0, _imgWidth, _imgHeight);
_iconImgView.image = img;
_iconImgView.contentMode = _imgContentMode;
}
}
}
///文本处理,主要是设置文本的宽高
- (void)p_actionForInitTextLabel {
_textLbl.backgroundColor = _textBackgroundColor;
if (_text) {
_textLbl.text = _text;
_textLbl.font = _textFont;
_textLbl.textColor = _textColor;
}
if (_attText) {
_textLbl.attributedText = _attText;
}
[_textLbl sizeToFit];
}
///子文本处理,主要是设置子文本的宽高
- (void)p_actionForInitSubTextLabel {
_subTextLbl.backgroundColor = _subTextBackgroundColor;
if (_subText) {
_subTextLbl.text = _subText;
_subTextLbl.font = _subTextFont;
_subTextLbl.textColor = _subTextColor;
}
if (_subAttText) {
_subTextLbl.attributedText = _subAttText;
}
[_subTextLbl sizeToFit];
}
///按钮处理,主要是设置按钮的x和size
- (void)p_actionForInitButtons {
if (_btnTitlesArr && _btnTitlesArr.count) {
for (int i=0; i<_btnTitlesArr.count; i++) {
UIButton* btn = UIButton.alloc.init;
[btn setTitle:_btnTitlesArr[i] forState:UIControlStateNormal];
if (_btnColorsArr && _btnColorsArr.count) {
@try {
[btn setTitleColor:_btnColorsArr[i] forState:UIControlStateNormal];
} @catch (NSException *exception) {
[btn setTitleColor:kLQHexColor(0x222222) forState:UIControlStateNormal];
} @finally {
}
}else {
[btn setTitleColor:kLQHexColor(0x222222) forState:UIControlStateNormal];
}
if (_btnFontsArr && _btnFontsArr.count) {
@try {
btn.titleLabel.font = _btnFontsArr[I];
} @catch (NSException *exception) {
btn.titleLabel.font = [UIFont systemFontOfSize:15];
} @finally {
}
}else {
btn.titleLabel.font = [UIFont systemFontOfSize:15];
}
if (_btnBorderWidthArr && _btnBorderWidthArr.count) {
@try {
btn.layer.borderWidth = _btnBorderWidthArr[i].floatValue;
} @catch (NSException *exception) {
btn.layer.borderWidth = 0;
} @finally {
}
}
if (_btnBorderColorArr && _btnBorderColorArr.count) {
@try {
btn.layer.borderColor = _btnBorderColorArr[i].CGColor;
} @catch (NSException *exception) {
} @finally {
}
}
if (_btnCornerRadiusArr && _btnCornerRadiusArr.count) {
@try {
btn.layer.cornerRadius = _btnCornerRadiusArr[i].floatValue;
} @catch (NSException *exception) {
btn.layer.cornerRadius = 0;
} @finally {
}
}
if (_btnBackgroundColorsArr && _btnBackgroundColorsArr.count) {
@try {
btn.backgroundColor = _btnBackgroundColorsArr[I];
} @catch (NSException *exception) {
} @finally {
}
}
CGFloat width = (_parentView.frame.size.width-_marginLeftXLeftButton-_marginRightXRightButton-(_btnTitlesArr.count-1)*_marginBetweenButtons)/_btnTitlesArr.count;
CGFloat x = _marginLeftXLeftButton+i*(width+_marginBetweenButtons);
btn.frame = CGRectMake(x, 0, width, _btnHeight);
btn.tag = I;
[btn addTarget:self action:@selector(p_actionForClickButton:) forControlEvents:UIControlEventTouchUpInside];
[self.buttonArrM addObject:btn];
[self addSubview:btn];
}
}
}
///更新控件的位置
- (void)p_actionForUpdateOrigin {
//计算所有控件的有效高度
CGFloat totalHeight = self.iconImgView.frame.size.height+self.textLbl.frame.size.height+self.subTextLbl.frame.size.height+self.buttonArrM.firstObject.frame.size.height+self.marginBetweenImageAndText+self.marginBetweenTextAndSubText+self.marginBetweenSubTextAndButton;
//计算控件的位置
CGFloat originalY = (self.parentView.frame.size.height-totalHeight)*0.5;
CGRect frame = self.iconImgView.frame;
CGFloat x = (self.parentView.frame.size.width-self.imgWidth)*0.5;
CGFloat y = originalY;
self.iconImgView.frame = CGRectMake(x, originalY, self.imgWidth, self.imgHeight);
frame = self.textLbl.frame;
x = (self.parentView.frame.size.width-frame.size.width)*0.5;
y = CGRectGetMaxY(self.iconImgView.frame)+self.marginBetweenImageAndText;
self.textLbl.frame = CGRectMake(x, y, frame.size.width, frame.size.height);
frame = self.subTextLbl.frame;
x = (self.parentView.frame.size.width-frame.size.width)*0.5;
y = CGRectGetMaxY(self.textLbl.frame)+self.marginBetweenTextAndSubText;
self.subTextLbl.frame = CGRectMake(x, y, frame.size.width, frame.size.height);
__weak typeof(self) weakSelf = self;
[self.buttonArrM enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
CGRect frame = obj.frame;
CGFloat y = CGRectGetMaxY(weakSelf.subTextLbl.frame)+weakSelf.marginBetweenSubTextAndButton;
obj.frame = CGRectMake(frame.origin.x, y, frame.size.width, frame.size.height);
}];
//计算异常界面的实际尺寸和位置
self.frame = self.parentView.bounds;
}
///点击按钮回调
- (void)p_actionForClickButton:(UIButton *)sender {
if (self.abnormalEventBlock) {
self.abnormalEventBlock(sender.tag);
}
}
- (void)p_actionForTapGesture {
if (self.isAllowTouchCallback) {
if (self.abnormalEventBlock) {
self.abnormalEventBlock(-1);
}
}
}
- (void)dealloc {
NSLog(@"dealloc --- %@", NSStringFromClass(self.class));
}
@end
调用举例
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
[self.view addSubview:self.tableView];
self.tableView.sx_networkDelegate = self;
self.tableView.sx_configDelegate = self;
[self.tableView sx_initRequestData];
LQAbnormalView* abnormalView = [[LQAbnormalView alloc] init];
abnormalView.imgName = @"语音按键";
abnormalView.imgBackgroundColor = UIColor.lightGrayColor;
NSString* text = @"对不起,你无权查看此文件,请联系你的直接上司修改权限";
abnormalView.text = text;
// abnormalView.attText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15], NSForegroundColorAttributeName:UIColor.purpleColor}];
abnormalView.textFont = [UIFont systemFontOfSize:13];
abnormalView.textColor = UIColor.purpleColor;
abnormalView.textBackgroundColor = UIColor.lightGrayColor;
NSString* subtext = @"我就是不给你看,你能咋地,来打我呀,我怕你呀";
abnormalView.subText = subtext;
abnormalView.subTextFont = [UIFont systemFontOfSize:13];
abnormalView.subTextColor = UIColor.redColor;
abnormalView.subTextBackgroundColor = UIColor.lightGrayColor;
abnormalView.btnTitlesArr = @[@"取消", @"确定"];
abnormalView.btnColorsArr = @[UIColor.redColor];
abnormalView.btnFontsArr = @[[UIFont systemFontOfSize:20],[UIFont systemFontOfSize:16],[UIFont systemFontOfSize:16]];
abnormalView.btnBorderWidthArr = @[@0.5];
abnormalView.btnBorderColorArr = @[UIColor.lightGrayColor,UIColor.redColor];
abnormalView.btnCornerRadiusArr = @[@2];
abnormalView.btnHeight = 60;
abnormalView.btnBackgroundColorsArr = @[UIColor.purpleColor];
abnormalView.marginBetweenImageAndText = 10;
abnormalView.marginBetweenTextAndSubText = 20;
abnormalView.marginBetweenSubTextAndButton = 10;
abnormalView.marginLeftXText = 100;
abnormalView.marginRightXText = 60;
abnormalView.marginLeftXSubText = 80;
abnormalView.marginRightXSubText = 100;
abnormalView.marginLeftXLeftButton = 100;
abnormalView.marginRightXRightButton = 50;
abnormalView.marginBetweenButtons = 5;
abnormalView.allowTouchCallback = YES;
abnormalView.abnormalEventBlock = ^(NSInteger idx) {
NSLog(@"idx = %zd", idx);
};
[self.view addSubview:abnormalView];
}
实际效果展示