iOS开发-自定制封装AlertView
前言:大家都知道系统自带的UIAlertController
用着也挺不错的,那么为什么还要自己定制呢?小编是本着能够实现满足我们某些特定的UI弹窗样式而进行的自定制封装。在此只做了简单的实现demo,希望可以帮助到有需要的猿友们,大家可以在此基础上进行修改,达到满足自己需求的效果。
原理:创建一个view添加在window上,同时添加出现与消失的动画,来展示弹窗弹出与消失的效果。类方法直接输入相应的参数弹出弹窗,使代码更加简洁。
先看效果图如下:
AlertView.gif
下面一起来看代码:
首先创建一个继承于UIView
的类,在.h
文件中外漏如下方法:
#import <UIKit/UIKit.h>
@interface RHAlertView : UIView
/**
类方法弹出提示框
@param title 提示标题
@param message 提示信息内容
@param cancel 点击取消回调block
@param confirm 点击确定回调block
*/
+ (void)showAlertWithTitle:(NSString *)title message:(NSString *)message cancel:(void(^)(void))cancel confirm:(void(^)(void))confirm;
/**
类方法弹出提示框
@param title 提示标题
@param message 提示信息内容
@param cancel 点击取消回调block
*/
+ (void)showAlertWithTitle:(NSString *)title message:(NSString *)message cancel:(void(^)(void))cancel;
/**
类方法弹出提示框
@param title 提示标题
@param message 提示信息内容
@param confirm 点击确定回调block
*/
+ (void)showAlertWithTitle:(NSString *)title message:(NSString *)message confirm:(void(^)(void))confirm;
@end
类方法调用,可以直接弹出弹窗,使代码看起来更加简洁。
接下来在.m
中来实现这几个方法。
首先要创建控件添加到该view上边,如下:
#pragma mark - init
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self addSubviews];
}
return self;
}
- (void)addSubviews {
[self addSubview:self.view_bg];
[_view_bg addSubview:self.lab_title];
[_view_bg addSubview:self.lab_message];
[_view_bg addSubview:self.lab_lineH];
[_view_bg addSubview:self.btn_cancel];
[_view_bg addSubview:self.lab_lineV];
[_view_bg addSubview:self.btn_confirm];
}
- (void)layoutSubviews {
self.frame = [UIApplication sharedApplication].keyWindow.bounds;
}
#pragma mark - button event
- (void)clickCancel:(UIButton *)sender {
if (self.cancelBlock) {
self.cancelBlock();
}
[self remove];
}
- (void)clickConfirm:(UIButton *)sender {
if (self.confirmBlock) {
self.confirmBlock();
}
[self remove];
}
#pragma mark - setter and getter
- (UIView *)view_bg {
if (!_view_bg) {
_view_bg = [[UIView alloc] init];
_view_bg.backgroundColor = [UIColor whiteColor];
_view_bg.layer.cornerRadius = 5.0;
_view_bg.layer.masksToBounds = YES;
_view_bg.alpha = 0;
}
return _view_bg;
}
- (UILabel *)lab_title {
if (!_lab_title) {
_lab_title = [[UILabel alloc] init];
_lab_title.font = [UIFont boldSystemFontOfSize:17];
_lab_title.textAlignment = NSTextAlignmentCenter;
_lab_title.numberOfLines = 0;
}
return _lab_title;
}
- (UILabel *)lab_message {
if (!_lab_message) {
_lab_message = [[UILabel alloc] init];
_lab_message.font = [UIFont systemFontOfSize:13];
_lab_message.textAlignment = NSTextAlignmentCenter;
_lab_message.numberOfLines = 0;
}
return _lab_message;
}
- (UILabel *)lab_lineH {
if (!_lab_lineH) {
_lab_lineH = [[UILabel alloc] init];
_lab_lineH.backgroundColor = Color_RGB(230, 230, 230);
}
return _lab_lineH;
}
- (UILabel *)lab_lineV {
if (!_lab_lineV) {
_lab_lineV = [[UILabel alloc] init];
_lab_lineV.backgroundColor = Color_RGB(230, 230, 230);
}
return _lab_lineV;
}
- (UIButton *)btn_cancel {
if (!_btn_cancel) {
_btn_cancel = [[UIButton alloc] init];
_btn_cancel.titleLabel.font = [UIFont systemFontOfSize:16];
[_btn_cancel setTitle:@"取消" forState:UIControlStateNormal];
[_btn_cancel setTitleColor:Color_RGB(69, 111, 239) forState:UIControlStateNormal];
[_btn_cancel addTarget:self action:@selector(clickCancel:) forControlEvents:UIControlEventTouchUpInside];
}
return _btn_cancel;
}
- (UIButton *)btn_confirm {
if (!_btn_confirm) {
_btn_confirm = [[UIButton alloc] init];
_btn_confirm.titleLabel.font = [UIFont systemFontOfSize:16];
[_btn_confirm setTitle:@"确定" forState:UIControlStateNormal];
[_btn_confirm setTitleColor:Color_RGB(55, 55, 55) forState:UIControlStateNormal];
[_btn_confirm addTarget:self action:@selector(clickConfirm:) forControlEvents:UIControlEventTouchUpInside];
}
return _btn_confirm;
}
这里,小编只是创建了几个常用控件添加到了self
上边,大家可以根据自己的需求进行修改,定义需要的控件添加到self
上边。大家可以看到,这里并没有给所有的控件添加约束,只设置self
的frame
等于window的bounds
。小编是这么想的,由于传入的标题和内容字数不固定,所以所有的约束在设置好标题和内容之后再进行添加。
下面我们来实现在.h
中外漏的几个方法:
/**
类方法弹出提示框
@param title 提示标题
@param message 提示信息内容
@param cancel 点击取消回调block
@param confirm 点击确定回调block
*/
+ (void)showAlertWithTitle:(NSString *)title message:(NSString *)message cancel:(void(^)(void))cancel confirm:(void(^)(void))confirm {
RHAlertView * alert = [[RHAlertView alloc] init];
//计算title和message需要的高度,并赋值
CGFloat titleHeight = 0;
CGFloat messageHeight = 0;
if (title.length == 0 && message.length == 0) {
alert.lab_message.text = @"输入title和message为空";
messageHeight = [alert getHeightByText:alert.lab_message.text font:[UIFont systemFontOfSize:13] width:Label_Width] + 2;
} else if (title.length == 0) {
alert.lab_message.text = message;
messageHeight = [alert getHeightByText:message font:[UIFont systemFontOfSize:13] width:Label_Width] + 2;
} else if (message.length == 0) {
alert.lab_title.text = title;
titleHeight = [alert getHeightByText:alert.lab_title.text font:[UIFont boldSystemFontOfSize:17] width:Label_Width] + 2;
} else {
alert.lab_title.text = title;
alert.lab_message.text = message;
titleHeight = [alert getHeightByText:alert.lab_title.text font:[UIFont boldSystemFontOfSize:17] width:Label_Width] + 2;
messageHeight = [alert getHeightByText:message font:[UIFont systemFontOfSize:13] width:Label_Width] + 2;
}
// 添加约束
[alert makeConstraintsWithAlert:alert titleHeight:titleHeight message:messageHeight isShowCancel:YES isShowConfirm:YES];
// 设置block
if (cancel) {
alert.cancelBlock = cancel;
}
if (confirm) {
alert.confirmBlock = confirm;
}
// 弹窗弹出
[alert show:alert];
}
/**
类方法弹出提示框
@param title 提示标题
@param message 提示信息内容
@param cancel 点击取消回调block
*/
+ (void)showAlertWithTitle:(NSString *)title message:(NSString *)message cancel:(void(^)(void))cancel {
RHAlertView * alert = [[RHAlertView alloc] init];
CGFloat titleHeight = 0;
CGFloat messageHeight = 0;
if (title.length == 0 && message.length == 0) {
alert.lab_message.text = @"输入title和message为空";
messageHeight = [alert getHeightByText:alert.lab_message.text font:[UIFont systemFontOfSize:13] width:Label_Width] + 2;
} else if (title.length == 0) {
alert.lab_message.text = message;
messageHeight = [alert getHeightByText:message font:[UIFont systemFontOfSize:13] width:Label_Width] + 2;
} else if (message.length == 0) {
alert.lab_title.text = title;
titleHeight = [alert getHeightByText:alert.lab_title.text font:[UIFont boldSystemFontOfSize:17] width:Label_Width] + 2;
} else {
alert.lab_title.text = title;
alert.lab_message.text = message;
titleHeight = [alert getHeightByText:alert.lab_title.text font:[UIFont boldSystemFontOfSize:17] width:Label_Width] + 2;
messageHeight = [alert getHeightByText:message font:[UIFont systemFontOfSize:13] width:Label_Width] + 2;
}
[alert makeConstraintsWithAlert:alert titleHeight:titleHeight message:messageHeight isShowCancel:YES isShowConfirm:NO];
if (cancel) {
alert.cancelBlock = cancel;
}
[alert show:alert];
}
/**
类方法弹出提示框
@param title 提示标题
@param message 提示信息内容
@param confirm 点击确定回调block
*/
+ (void)showAlertWithTitle:(NSString *)title message:(NSString *)message confirm:(void(^)(void))confirm {
RHAlertView * alert = [[RHAlertView alloc] init];
CGFloat titleHeight = 0;
CGFloat messageHeight = 0;
if (title.length == 0 && message.length == 0) {
alert.lab_message.text = @"输入title和message为空";
messageHeight = [alert getHeightByText:alert.lab_message.text font:[UIFont systemFontOfSize:13] width:Label_Width] + 2;
} else if (title.length == 0) {
alert.lab_message.text = message;
messageHeight = [alert getHeightByText:message font:[UIFont systemFontOfSize:13] width:Label_Width] + 2;
} else if (message.length == 0) {
alert.lab_title.text = title;
titleHeight = [alert getHeightByText:alert.lab_title.text font:[UIFont boldSystemFontOfSize:17] width:Label_Width] + 2;
} else {
alert.lab_title.text = title;
alert.lab_message.text = message;
titleHeight = [alert getHeightByText:alert.lab_title.text font:[UIFont boldSystemFontOfSize:17] width:Label_Width] + 2;
messageHeight = [alert getHeightByText:message font:[UIFont systemFontOfSize:13] width:Label_Width] + 2;
}
[alert makeConstraintsWithAlert:alert titleHeight:titleHeight message:messageHeight isShowCancel:NO isShowConfirm:YES];
if (confirm) {
alert.confirmBlock = confirm;
}
[alert show:alert];
}
#pragma mark - private
- (CGFloat)getHeightByText:(NSString *)text font:(UIFont *)font width:(CGFloat)width {
UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 0)];
label.text = text;
label.font = font;
label.numberOfLines = 0;
[label sizeToFit];
CGFloat height = label.frame.size.height;
return height;
}
- (void)show:(RHAlertView *)alert {
UIWindow * window = [UIApplication sharedApplication].keyWindow;
[window addSubview:alert];
[UIView animateWithDuration:0.25 animations:^{
alert.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3];
alert.view_bg.alpha = 1.0;
}];
}
- (void)remove {
__weak typeof(self)weakSelf = self;
[UIView animateWithDuration:0.25 animations:^{
weakSelf.alpha = 0;
} completion:^(BOOL finished) {
[weakSelf removeFromSuperview];
}];
}
- (void)makeConstraintsWithAlert:(RHAlertView *)alert titleHeight:(CGFloat)titleHeight message:(CGFloat)messageHeight isShowCancel:(BOOL)isShowCancel isShowConfirm:(BOOL)isShowConfirm {
CGFloat viewHeight = Button_Height + 1;
if (titleHeight > 0 && messageHeight > 0) {
viewHeight = viewHeight + 20 + messageHeight + 15 + titleHeight + 20;
} else if (titleHeight > 0) {
viewHeight = viewHeight + 20 + titleHeight + 20;
} else if (messageHeight > 0) {
viewHeight = viewHeight + 20 + messageHeight + 20;
}
// viewBG
[alert.view_bg makeConstraints:^(RHConstraintMaker *maker) {
maker.centerX(0);
maker.centerY(0);
maker.width(BG_Width);
maker.height(viewHeight);
}];
// labTitle
[alert.lab_title makeConstraints:^(RHConstraintMaker *maker) {
maker.centerX(0);
maker.top(20);
maker.width(Label_Width);
maker.height(titleHeight);
}];
// labMessage
[alert.lab_message makeConstraints:^(RHConstraintMaker *maker) {
maker.centerX(0);
maker.bottom(-Button_Height - 1 - 20);
maker.width(Label_Width);
maker.height(messageHeight);
}];
// lineH
[alert.lab_lineH makeConstraints:^(RHConstraintMaker *maker) {
maker.left(0);
maker.bottom(-Button_Height);
maker.right(0);
maker.height(1);
}];
if (isShowCancel && isShowConfirm) {
// btnCancel
[alert.btn_cancel makeConstraints:^(RHConstraintMaker *maker) {
maker.left(0);
maker.bottom(0);
maker.width(Button_Width);
maker.height(Button_Height);
}];
// btnConfirm
[alert.btn_confirm makeConstraints:^(RHConstraintMaker *maker) {
maker.right(0);
maker.bottom(0);
maker.width(Button_Width);
maker.height(Button_Height);
}];
// lineV
[alert.lab_lineV makeConstraints:^(RHConstraintMaker *maker) {
maker.centerX(0);
maker.bottom(0);
maker.width(1);
maker.height(Button_Height);
}];
} else if (isShowCancel) {
[alert.btn_confirm removeFromSuperview];
[alert.lab_lineV removeFromSuperview];
// btnCancel
[alert.btn_cancel makeConstraints:^(RHConstraintMaker *maker) {
maker.left(0);
maker.bottom(0);
maker.right(0);
maker.height(Button_Height);
}];
} else if (isShowConfirm) {
[alert.btn_cancel removeFromSuperview];
[alert.lab_lineV removeFromSuperview];
// btnConfirm
[alert.btn_confirm makeConstraints:^(RHConstraintMaker *maker) {
maker.right(0);
maker.bottom(0);
maker.left(0);
maker.height(Button_Height);
}];
}
}
由于title
和message
高度不固定,所以添加约束之前要先计算他们需要的高度各是多少。这里的添加约束是小编使用系统原生NSLayoutConstraint
简单封装的一个添加约束的工具类,大家可以修改为自己常使用的添加约束工具类。到此,封装就完成了。
下面,我们来看一下如何使用:
- (void)viewDidLoad {
[super viewDidLoad];
UIButton * btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 40)];
btn.backgroundColor = [UIColor orangeColor];
[btn setTitle:@"ShowAlert" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)clickButton:(UIButton *)sender {
[RHAlertView showAlertWithTitle:@"AlertView_Title" message:@"AlertView_Message:今天是个好天气!适合出去游玩,但是没有人陪伴,所以只能独自在家撸代码!" cancel:^{
NSLog(@"点击了取消!");
} confirm:^{
NSLog(@"点击了确定!");
}];
// [RHAlertView showAlertWithTitle:@"AlertView_Title" message:@"AlertView_Message:今天是个好天气!适合出去游玩,但是没有人陪伴,所以只能独自在家撸代码!" cancel:^{
//
// NSLog(@"点击了取消!");
// }];
//
// [RHAlertView showAlertWithTitle:@"AlertView_Title" message:@"AlertView_Message:今天是个好天气!适合出去游玩,但是没有人陪伴,所以只能独自在家撸代码!" confirm:^{
//
// NSLog(@"点击了确定!");
// }];
}
大家可以明显看到,代码非常的简洁,并且使用方法非常的简单。
如果还有什么不清晰的地方,欢迎随时提问,小编会在看到的第一时间回复。demo下载地址:https://github.com/guorenhao/RHAlertView.git
最后,希望能够帮助到有需要的猿友们,希望同是程序猿的我们能够共同进步,在开发的道路上越走越远!祝大家生活愉快!谢谢!