永不过时的自定义AlertView
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了永不过时的自定义AlertView相关的知识,希望对你有一定的参考价值。
码农门都知道,再好的项目如果用户体验跟不上的话也就死了一半了,特别是网络这块,经常需要我们弹出各种提示框,这就需要用到alertView了,但是ios8以后alertView就被alertController替代了 而项目中用我们又经常需要用到它,今天笔者就为大家带来一个可以显著提升用户体验度,直接继承至UIWindow的高度自定义AlertView(永不过时),希望大家喜欢!废话不多说,直接上代码
.h文件如下
// // Prompt.h // CustomAlertView // // Created by jacke-xu on 16/6/4. // Copyright © 2016年 jacke-xu. All rights reserved. // #import <UIKit/UIKit.h> //点击样式 typedef NS_ENUM(NSInteger, MyWindowClick){ MyWindowClickForOK = 0,//点击确定按钮 MyWindowClickForCancel//点击取消按钮 }; //提示框显示样式 typedef NS_ENUM(NSInteger, PromptStyle) { PromptStyleDefalut = 0,//默认样式 ——成功 PromptStyleSuccess,//成功 PromptStyleFail,//失败 PromptStyleWaring//警告 }; typedef void (^callBack)(MyWindowClick buttonIndex); @interface Prompt : UIWindow @property (nonatomic, copy) callBack clickBlock ;//按钮点击事件的回调 + (instancetype)shared; /** * 创建Prompt并展示 * * @param style 绘制的图片样式 * @param title 警示标题 * @param detail 警示内容 * @param canle 取消按钮标题 * @param ok 确定按钮标题 * @param callBack 按钮点击时间回调 * * @return 返回Prompt */ + (instancetype)showPromptWithStyle:(PromptStyle)style title:(NSString *)title detail:(NSString *)detail canleButtonTitle:(NSString *)canle okButtonTitle:(NSString *)ok callBlock:(callBack)callBack; //默认样式创建Prompt + (instancetype)showPromptWithTitle:(NSString *)title detail:(NSString *)detail canleButtonTitle:(NSString *)canle okButtonTitle:(NSString *)ok callBlock:(callBack)callBack; @end
再来.m
// // Prompt.m // CustomAlertView // // Created by jacke-xu on 16/6/4. // Copyright © 2016年 jacke-xu. All rights reserved. // #import "Prompt.h" //按钮颜色 #define OKBUTTON_BGCOLOR [UIColor colorWithRed:158/255.0 green:214/255.0 blue:243/255.0 alpha:1] #define CANCELBUTTON_BGCOLOR [UIColor colorWithRed:255/255.0 green:20/255.0 blue:20/255.0 alpha:1] //按钮起始tag #define TAG 100 #define SCREEN_Width [UIScreen mainScreen].bounds.size.width #define SCREEN_Height [UIScreen mainScreen].bounds.size.height NSUInteger const Button_Size_Width = 80; NSUInteger const Button_Size_Height = 30; NSInteger const Title_Font = 18; NSInteger const Detial_Font = 16; //Logo半径(画布) NSInteger const Logo_Size = 40; NSInteger const Button_Font = 16; @interface Prompt () { UIView * _logoView;//画布 UILabel * _titleLabel;//标题 UILabel * _detailLabel;//详情 UIButton * _OkButton;//确定按钮 UIButton * _canleButton;//取消按钮 CAShapeLayer * _pathLayer;//尝试保护内存 } @end @implementation Prompt + (instancetype)showPromptWithStyle:(PromptStyle)style title:(NSString *)title detail:(NSString *)detail canleButtonTitle:(NSString *)canle okButtonTitle:(NSString *)ok callBlock:(callBack)callBack { switch (style) { case PromptStyleDefalut: [[self shared] drawRight]; break; case PromptStyleSuccess: [[self shared] drawRight]; break; case PromptStyleFail: [[self shared] drawWrong]; break; case PromptStyleWaring: [[self shared] drawWaring]; break; default: break; } [[self shared] addButtonTitleWithCancle:canle OK:ok]; [[self shared] addTitle:title detail:detail]; [[self shared] setClickBlock:nil];//释放掉之前的Block [[self shared] setClickBlock:callBack]; [[self shared] setHidden:NO];//设置为不隐藏 return [self shared]; } + (instancetype)showPromptWithTitle:(NSString *)title detail:(NSString *)detail canleButtonTitle:(NSString *)canle okButtonTitle:(NSString *)ok callBlock:(callBack)callBack { return [self showPromptWithStyle:PromptStyleSuccess title:title detail:detail canleButtonTitle:canle okButtonTitle:ok callBlock:callBack]; } //单例 + (instancetype)shared { static dispatch_once_t once = 0; static Prompt *prompt; dispatch_once(&once, ^{ prompt = [[Prompt alloc] init]; }); return prompt; } - (instancetype)init { self = [super init]; if (self) { self.frame = (CGRect) {{0.f,0.f}, [[UIScreen mainScreen] bounds].size}; self.alpha = 1; [self setBackgroundColor:[UIColor clearColor]]; self.hidden = NO;//不隐藏 self.windowLevel = 100; [self setInterFace]; } return self; } /** * 界面初始化 */ - (void)setInterFace { [self logoInit]; [self controlsInit]; } /** * 初始化控件 */ - (void)controlsInit { CGFloat x = _logoView.frame.origin.x; CGFloat y = _logoView.frame.origin.y; CGFloat height = _logoView.frame.size.height; CGFloat width = _logoView.frame.size.width; _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(x ,y + height / 2, width, Title_Font + 5)]; [_titleLabel setFont:[UIFont systemFontOfSize:Title_Font]]; [_titleLabel setTextAlignment:NSTextAlignmentCenter]; _detailLabel = [[UILabel alloc] initWithFrame:CGRectMake(x ,y + height / 2 + (Title_Font + 10), width, Detial_Font + 5)]; _detailLabel.textColor = [UIColor grayColor]; [_detailLabel setFont:[UIFont systemFontOfSize:Detial_Font]]; [_detailLabel setTextAlignment:NSTextAlignmentCenter]; CGFloat centerY = _detailLabel.center.y + 40; _OkButton = [UIButton buttonWithType:UIButtonTypeCustom]; _OkButton.layer.cornerRadius = 5; _OkButton.titleLabel.font = [UIFont systemFontOfSize:Button_Font]; _OkButton.center = CGPointMake(_detailLabel.center.x + 50, centerY); _OkButton.bounds = CGRectMake(0, 0, Button_Size_Width, Button_Size_Height); _OkButton.backgroundColor = OKBUTTON_BGCOLOR; _canleButton = [UIButton buttonWithType:UIButtonTypeCustom]; _canleButton.center = CGPointMake(_detailLabel.center.x - 50, centerY); _canleButton.bounds = CGRectMake(0, 0, Button_Size_Width, Button_Size_Height); _canleButton.backgroundColor = CANCELBUTTON_BGCOLOR; _canleButton.layer.cornerRadius = 5; _canleButton.titleLabel.font = [UIFont systemFontOfSize:Button_Font]; [self addSubview:_titleLabel]; [self addSubview:_detailLabel]; [self addSubview:_OkButton]; [self addSubview:_canleButton]; _canleButton.hidden = YES; _OkButton.hidden = YES; _OkButton.tag = TAG; _canleButton.tag = TAG + 1; [_OkButton addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside]; [_canleButton addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside]; } /** * 初始化logo视图——画布 */ // 需完善画布的清除,不适用移除,新建的办法 - (void)logoInit { //移除画布 [_logoView removeFromSuperview]; _logoView = nil; //新建画布 _logoView = [UIView new]; _logoView.center = CGPointMake(self.center.x, self.center.y - 40); _logoView.bounds = CGRectMake(0, 0, 320 / 1.5, 320 / 1.5); _logoView.backgroundColor = [UIColor whiteColor]; _logoView.layer.cornerRadius = 10; _logoView.layer.shadowColor = [UIColor blackColor].CGColor; _logoView.layer.shadowOffset = CGSizeMake(0, 5); _logoView.layer.shadowOpacity = 0.3f; _logoView.layer.shadowRadius = 10.0f; //保证画布位于所有视图层级的最下方 if (_titleLabel != nil) { [self insertSubview:_logoView belowSubview:_titleLabel]; } else [self addSubview:_logoView]; } /** * 添加按钮 * * @param cancle 按钮标题 * @param ok 按钮标题 */ - (void) addButtonTitleWithCancle:(NSString *)cancle OK:(NSString *)ok { BOOL flag = NO; if (cancle == nil && ok != nil ) { flag = YES; } CGFloat centerY = _detailLabel.center.y + 40; if (flag) { _OkButton.center = CGPointMake(_detailLabel.center.x, centerY); _OkButton.bounds = CGRectMake(0, 0, Button_Size_Width, Button_Size_Height); _canleButton.hidden = YES; } else { _canleButton.hidden = NO; [_canleButton setTitle:cancle forState:UIControlStateNormal]; _OkButton.center = CGPointMake(_detailLabel.center.x + 50, centerY); _OkButton.bounds = CGRectMake(0, 0, Button_Size_Width, Button_Size_Height); } _OkButton.hidden = NO; [_OkButton setTitle:ok forState:UIControlStateNormal]; } /** * 添加标题信息和详细信息 * * @param title 标题内容 * @param detail 详细内容 */ - (void)addTitle:(NSString *)title detail:(NSString *)detail { _titleLabel.text = title; _detailLabel.text = detail; } /** * 画圆和勾 */ -(void) drawRight { [self logoInit]; //自绘制图标中心点 CGPoint pathCenter = CGPointMake(_logoView.frame.size.width/2, _logoView.frame.size.height/2 - 50); UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:pathCenter radius:Logo_Size startAngle:0 endAngle:M_PI*2 clockwise:YES]; path.lineCapStyle = kCGLineCapRound; path.lineJoinStyle = kCGLineCapRound; CGFloat x = _logoView.frame.size.width/2.5 + 5; CGFloat y = _logoView.frame.size.height/2 - 45; //勾的起点 [path moveToPoint:CGPointMake(x, y)]; //勾的最底端 CGPoint p1 = CGPointMake(x+10, y+ 10); [path addLineToPoint:p1]; //勾的最上端 CGPoint p2 = CGPointMake(x+35,y-20); [path addLineToPoint:p2]; //新建图层——绘制上面的圆圈和勾 CAShapeLayer *layer = [[CAShapeLayer alloc] init]; layer.fillColor = [UIColor clearColor].CGColor; layer.strokeColor = [UIColor greenColor].CGColor; layer.lineWidth = 5; layer.path = path.CGPath; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:NSStringFromSelector(@selector(strokeEnd))]; animation.fromValue = @0; animation.toValue = @1; animation.duration = 0.5; [layer addAnimation:animation forKey:NSStringFromSelector(@selector(strokeEnd))]; [_logoView.layer addSublayer:layer]; } /** * 画三角形以及感叹号 */ -(void) drawWaring { // [_logoView removeFromSuperview]; [self logoInit]; //自绘制图标中心店 UIBezierPath *path = [UIBezierPath bezierPath]; path.lineCapStyle = kCGLineCapRound; path.lineJoinStyle = kCGLineCapRound; //绘制三角形 CGFloat x = _logoView.frame.size.width/2; CGFloat y = 15; //三角形起点(上方) [path moveToPoint:CGPointMake(x, y)]; //左边 CGPoint p1 = CGPointMake(x - 45, y + 80); [path addLineToPoint:p1]; //右边 CGPoint p2 = CGPointMake(x + 45,y + 80); [path addLineToPoint:p2]; //关闭路径 [path closePath]; //绘制感叹号 //绘制直线 [path moveToPoint:CGPointMake(x, y + 20)]; CGPoint p4 = CGPointMake(x, y + 60); [path addLineToPoint:p4]; //绘制实心圆 [path moveToPoint:CGPointMake(x, y + 70)]; [path addArcWithCenter:CGPointMake(x, y + 70) radius:2 startAngle:0 endAngle:M_PI*2 clockwise:YES]; //新建图层——绘制上述路径 CAShapeLayer *layer = [[CAShapeLayer alloc] init]; layer.fillColor = [UIColor clearColor].CGColor; layer.strokeColor = [UIColor orangeColor].CGColor; layer.lineWidth = 5; layer.path = path.CGPath; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:NSStringFromSelector(@selector(strokeEnd))]; animation.fromValue = @0; animation.toValue = @1; animation.duration = 0.5; [layer addAnimation:animation forKey:NSStringFromSelector(@selector(strokeEnd))]; [_logoView.layer addSublayer:layer]; } /** * 画圆角矩形和叉 */ - (void)drawWrong { [self logoInit]; CGFloat x = _logoView.frame.size.width / 2 - Logo_Size; CGFloat y = 15; //圆角矩形 UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(x, y, Logo_Size * 2, Logo_Size * 2) cornerRadius:5]; path.lineCapStyle = kCGLineCapRound; path.lineJoinStyle = kCGLineCapRound; CGFloat space = 20; //斜线1 [path moveToPoint:CGPointMake(x + space, y + space)]; CGPoint p1 = CGPointMake(x + Logo_Size * 2 - space, y + Logo_Size * 2 - space); [path addLineToPoint:p1]; //斜线2 [path moveToPoint:CGPointMake(x + Logo_Size * 2 - space , y + space)]; CGPoint p2 = CGPointMake(x + space, y + Logo_Size * 2 - space); [path addLineToPoint:p2]; //新建图层——绘制上述路径 CAShapeLayer *layer = [[CAShapeLayer alloc] init]; layer.fillColor = [UIColor clearColor].CGColor; layer.strokeColor = [UIColor redColor].CGColor; layer.lineWidth = 5; layer.path = path.CGPath; //使用NSStringFromSelector(@selector(strokeEnd))作为KeyPath的作用,绘制动画每一次Show均重复运行 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:NSStringFromSelector(@selector(strokeEnd))]; animation.fromValue = @0; animation.toValue = @1; animation.duration = 0.5; //和上对应 [layer addAnimation:animation forKey:NSStringFromSelector(@selector(strokeEnd))]; [_logoView.layer addSublayer:layer]; } /** * * 按钮点击事件 * * @param sender 按钮 */ - (void)buttonClick:(UIButton *)sender { self.clickBlock(sender.tag - TAG); } @end
调用方法:
// // ViewController.m // CustomAlertView // // Created by jacke-xu on 16/6/4. // Copyright © 2016年 jacke-xu. All rights reserved. // #import "ViewController.h" #import "Prompt.h" @interface ViewController () { UIWindow *__sheetWindow;//window必须为全局变量或成员变量 } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.view.backgroundColor = [UIColor whiteColor]; CGFloat x = self.view.center.x ; CGFloat y = self.view.center.y - 200; NSArray * textArray = @[@"成功",@"失败",@"警告"]; for (NSUInteger i = 0; i < 3 ; i ++) { UIButton * successButton = [UIButton buttonWithType:UIButtonTypeSystem]; [successButton setTitle:textArray[i] forState:UIControlStateNormal]; successButton.center = CGPointMake(x, y); successButton.bounds = CGRectMake(0, 0, 100, 30); [self.view addSubview:successButton]; [successButton addTarget:self action:@selector(show:) forControlEvents:UIControlEventTouchUpInside]; successButton.tag = 60 + i; y += 60; } } - (void)show:(UIButton *)sender { NSString * title = nil; NSString * detail = nil; NSString * cancle = @"取消"; NSString * ok = @"确定"; switch (sender.tag - 59) { case PromptStyleSuccess: case PromptStyleDefalut: title = @"温馨提示"; detail = @"登录成功"; cancle = nil; break; case PromptStyleFail: title = @"错误提示"; detail = @"您输入的号码有误。"; break; case PromptStyleWaring: title = @"警告"; detail = @"您正在进行非安全操作!!"; default: break; } //为成员变量Window赋值则立即显示Window __sheetWindow = [Prompt showPromptWithStyle:sender.tag - 59 title:title detail:detail canleButtonTitle:cancle okButtonTitle:ok callBlock:^(MyWindowClick buttonIndex) { //Window隐藏,并置为nil,释放内存 不能少 NSLog(@"用户点击了第%ld个按钮",(long)buttonIndex); __sheetWindow.hidden = YES; __sheetWindow = nil; }]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
项目源码请见 GitHub: https://github.com/Jacke-xu/CustomAlertView
以上是关于永不过时的自定义AlertView的主要内容,如果未能解决你的问题,请参考以下文章