iOS开发之使用画板和CA自定义有动画效果的AlertView

 本文主要介绍使用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>

最终的效果图:

        

完整代码在我的上传的资源中。

猜你喜欢

转载自blog.csdn.net/u014745414/article/details/44782331