永不过时的自定义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的主要内容,如果未能解决你的问题,请参考以下文章

优雅~永不过时。nacos+feign

那些让人赏心悦目的C语言代码,优雅永不过时!

找到我的自定义代码片段 Xcode 6?

python游戏制作拼图永不过时,这就是我这个年龄该玩的游戏~

经典永不过时!重温设计模式

永不过时的股市格言