本文主要介绍使用UIBezierPath,CAShapeLayer和CABasicAnimation 来自定义具有动画效果的弹出提示框(AlertView)。

1.在这里alertView继承的是UIWindow,

(1)基本思路是:在自定义的window添加一个子视图UIView,

(2)在view的层上添加一个子层CAShapeLayer,在子层上绘制UIBezierPath路径,往层上添加CABasicAnimation动画,动画按路径运行

(3)往window上添加两个UILabel显示消息标题和内容,添加一个取消按钮和一个确定按钮

2.实现步骤

(1)XSAlertView.h

<span style=”font-size:18px;”>typedef enum : NSInteger{

/**
* 点击确定按钮
*/
XSAlertViewClickOk,
/**
* 点击取消按钮
*/
XSAlertViewClickCancel

} XSAlertViewClickType;

/**
* 提示框的样式
*/
typedef enum : NSInteger {

XSAlertviewStyleDefault, // 默认样式—-成功
XSAlertviewStyleSuccess, // 成功
XSAlertviewStyleFail, // 失败
XSAlertviewStyleWaring // 警告

} XSAlerTviewStyle;

typedef void(^Completion)(XSAlertViewClickType buttonIndex);
@interface XSAlertView : UIWindow
{

}

// 按钮单击回调block
@property (nonatomic,strong)Completion completeBlock;

/**
* 单例
*
* @return 返回XSAlertView对象
*/
+ (id)shared;

/**
* 创建AlertView并展示
*
* @param style 绘制的图片样式
* @param title 警示标题
* @param message 警示内容
* @param cancel 取消按钮标题
* @param ok 确定按钮标题
* @param completion 按钮点击时回调
*
* @return 返回XSAlertView
*/
+ (id)showAlertWithStyle:(XSAlerTviewStyle)style title:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancel okButtonTitle:(NSString *)ok completion:(Completion)completion;</span></span>
(2)创建单例,节约内存
<span style=”font-size:18px;”>static XSAlertView *alertView = nil;
+(id)shared {

// 同步锁
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
alertView = [[XSAlertView alloc]init];

});

return alertView;
}</span>
(3)创建UIView,用于绘制logo
<span style=”font-size:18px;”>- (void)_logoInit {

// 移除上一次绘制
[_logoView removeFromSuperview];
_logoView = nil;

// 创建新画布
_logoView = [[UIView alloc]init];

_logoView.center = CGPointMake(self.center.x, self.center.y);
_logoView.bounds = CGRectMake(0.f, 0.f, kScreenWidth / 1.5f, kScreenHeight / 2.5f);
_logoView.backgroundColor = [UIColor colorWithWhite:1.f alpha:0.7f];
_logoView.layer.cornerRadius = 10.f;
_logoView.layer.shadowOffset = CGSizeMake(0.f, 5.f);
_logoView.layer.shadowColor = [UIColor blackColor].CGColor;
_logoView.layer.shadowOpacity = 0.3f; // 不透明度:0表示完全透明
_logoView.layer.shadowRadius = 10.f;

// 保证画布在*底层
if (_titleLabel != nil) {

[self insertSubview:_logoView belowSubview:_titleLabel];
}
else {

[self addSubview:_logoView];
}

}

</span>
(4)往window上添加按钮和标签,此处比较简单,代码简单繁琐,就不列出了。
(5)往_logoView的层上添加层,绘制路径,此处给出绘制提示正确的弹出框的图片代码
<span style=”font-size:18px;”>- (void)_drawRight {

// 初始化画布
[self _logoInit];

// 圆的中心
CGPoint pathCenter = CGPointMake(_logoView.frame.size.width / 2.f, _logoView.frame.size.height / 2.f – 50);

// 画圆(360度的弧线)
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:pathCenter radius:40.f startAngle:0 endAngle:M_PI * 2 clockwise:YES];

// 勾的起点坐标
CGFloat x = _logoView.frame.size.width / 2.5f + 5.f;
CGFloat y = _logoView.frame.size.height / 2.f – 45.f;

path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineCapRound;
// 画勾的起点
[path moveToPoint:CGPointMake(x, y)];
[path addLineToPoint:CGPointMake(x + 10.f, y + 10.f)];
[path addLineToPoint:CGPointMake(x + 35.f, y – 20.f)];

// 新建层
CAShapeLayer *layer = [[CAShapeLayer alloc]init];
layer.fillColor = [UIColor clearColor].CGColor;
layer.strokeColor = [UIColor greenColor].CGColor;
layer.lineWidth = 5.f;
layer.path = path.CGPath;

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@”strokeEnd”];
animation.fromValue = @0;
animation.toValue = @1;
animation.duration = 0.5f;
[layer addAnimation:animation forKey:@”strokeEnd”];

[_logoView.layer addSublayer:layer];

</span>
在这里值得一提的是,CAshapeLayer的strokeStart,strokeEnd与CABasicAnimation 的fromValue,toValue的用法和做出的效果下面是我个人对这个的总结:
<span style=”font-size:18px;”>1 keyPath = strokeStart 动画的fromValue = 0,toValue = 1

strokeEnd默认为1,strokeStart从 0 到 1 ,strokeStart = 0 时有一条完整的路径,strokeStart = 1 时 路径消失,效果就是一条从路径起点到终点慢慢的消失

2 keyPath = strokeStart 动画的fromValue = 1,toValue = 0

strokeEnd默认为1,strokeStart从 1 到 0 ,strokeStart = 1 时无路径,strokeStart = 0 时 画出一条完整的路径,效果就是一条从路径终点到起点慢慢的出现

3 keyPath = strokeEnd 动画的fromValue = 0,toValue = 1

strokeStart默认为0,strokeEnd从 0-1,strokeEnd=0 时,无路径,strokeEnd=1 时,一条完整路径。效果就是一条从路径起点到终点慢慢的出现

4 keyPath = strokeEnd 动画的fromValue = 1,toValue = 0

效果就是反方向路径慢慢消失</span>

(6)对类方法 的实现
<span style=”font-size:18px;”>/**
* 创建AlertView并展示
*
* @param style 绘制的图片样式
* @param title 警示标题
* @param message 警示内容
* @param cancel 取消按钮标题
* @param ok 确定按钮标题
* @param completion 按钮点击时回调
*
* @return 返回XSAlertView
*/</span>
<pre name=”code” class=”objc”><span style=”font-size:18px;”>+(id)showAlertWithStyle:(XSAlerTviewStyle)style title:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancel okButtonTitle:(NSString *)ok completion:(Completion)completion {

switch (style) {
// 成功、默认
case XSAlertviewStyleDefault:
case XSAlertviewStyleSuccess:
[[self shared] _drawRight];
break;

// 失败
case XSAlertviewStyleFail:
[[self shared] _drawWrong];
break;

// 警告
case XSAlertviewStyleWaring:
[[self shared] _drawWaring];
default:
break;
}
[[self shared] _addButtonTitleWithCancle:cancel OK:ok];
[[self shared] _addTitle:title message:message];
[[self shared] setCompleteBlock:nil];//释放掉之前的Block
[[self shared] setCompleteBlock:completion];
[[self shared] setHidden:NO];//设置为不隐藏

return [self shared];
</span>
}

(7) *后调用我们自己写的弹出框
<span style=”font-size:18px;”>- (void)show:(UIButton *)button {

NSString * title = nil;
NSString * message = nil;
NSString * cancle = @”取消”;
NSString * ok = @”确定”;
switch (button.tag+1) {
// 成功
case XSAlertviewStyleSuccess:
case XSAlertviewStyleDefault:
title = @”温馨提示”;
message = @”登录成功”;
cancle = nil;
break;
// 失败
case XSAlertviewStyleFail:
title = @”错误提示”;
message = @”您输入的号码有误。”;
break;
// 警告
case XSAlertviewStyleWaring:
title = @”警告”;
message = @”您确定要开抢吗!!”;
default:
break;
}
//为成员变量Window赋值则立即显示Window
_alertWindow = [XSAlertView showAlertWithStyle:button.tag+1 title:title message:message cancelButtonTitle:cancle okButtonTitle:ok completion:^(XSAlertViewClickType buttonIndex) {

if (buttonIndex == 0) {
NSLog(@”确定”);
// …
}
else {

NSLog(@”取消”);
// …
}
//Window隐藏
_sheetWindow.hidden = YES;

//置为nil,释放内存
_sheetWindow = nil;
}];

}
</span>
*终的效