iOS 封装 加载成功打勾和打叉状态动画

97 篇文章 0 订阅
79 篇文章 2 订阅

想必大家在加载过程中经常会遇到加载成功或者加载失败后进行一个动画提示,例如:加载完成或者加载失败变成对号或者句号。

这个方法我也是看了别人的项目,但是他的项目少了一部分代码,我这里给补上了。

下面就是这个动画的的效果

这个左面是成功动画、有面是失败动画

下面是代码,稍后我也会附上下载封装的代码

首先是AnimationView.h文件

@interface AnimationView : UIView

- (void)startSuccessAnimation;

- (void)startErrorAnimation;

@end

下面是AnimationView.m文件


#import "AnimationView.h"
#import "CCArcMoveLayer.h"

static NSString * const kName = @"name";

static CGFloat const kRadius = 20;
static CGFloat const kLineWidth = 3;
static CGFloat const kStep1Duration = 1.0;
static CGFloat const kStep2Duration = 0.5;

@interface AnimationView ()

@property (strong, nonatomic) CCArcMoveLayer *arcMoveLayer;
@property (strong, nonatomic) CAShapeLayer *checkLine;

@end

@implementation AnimationView

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor whiteColor];
        UIView *view = [[UIView alloc]initWithFrame:CGRectMake(1, 1, frame.size.width - 2, frame.size.width - 2)];
        view.layer.cornerRadius = (frame.size.width - 2) / 2;
        [self addSubview:view];
        view.backgroundColor = [UIColor clearColor];
        view.layer.borderColor = [[UIColor colorWithHexString:@"#F98680"] CGColor];
        view.layer.borderWidth = 1;
    }
    return self;
}

#pragma mark - public
- (void)startSuccessAnimation {
    [self reset];
    [self doSuccessStep1];
}

- (void)startErrorAnimation {
    [self reset];
    [self doErrorStep1];
}

#pragma mark - animation
- (void)reset {
    [self.arcMoveLayer removeFromSuperlayer];
    [self.checkLine removeFromSuperlayer];
}

#pragma mark - animation step stop
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    if ([[anim valueForKey:kName] isEqualToString:@"successStep1"]) {
        [self doSuccessStep2];
    } else if ([[anim valueForKey:kName] isEqualToString:@"errorStep1"]) {
        [self doErrorStep2];
    }
}
// 成功 第1阶段
- (void)doSuccessStep1 {
    self.arcMoveLayer = [CCArcMoveLayer layer];
    self.arcMoveLayer.contentsScale = [UIScreen mainScreen].scale;
    self.arcMoveLayer.bounds = CGRectMake(0, 0, kRadius * 2 + kLineWidth, kRadius * 2 + kLineWidth);
    self.arcMoveLayer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
    
    
    // animation
    self.arcMoveLayer.progress = 1; // end status
    [self.layer addSublayer:self.arcMoveLayer];
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"progress"];
    animation.duration = kStep1Duration;
    animation.fromValue = @0.0;
    animation.toValue = @1.0;
    animation.delegate = self;
    [animation setValue:@"successStep1" forKey:kName];
    [self.arcMoveLayer addAnimation:animation forKey:nil];
}

#pragma mark - success
//成功 第2阶段
- (void)doSuccessStep2 {
    self.checkLine = [CAShapeLayer layer];
    [self.layer addSublayer:self.checkLine];
    self.checkLine.frame = self.layer.bounds;
    // path
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    path.lineCapStyle = kCGLineCapSquare; //线条拐角
    path.lineJoinStyle = kCGLineCapRound; //终点处理
    
    [path moveToPoint:CGPointMake(CGRectGetMidX(self.bounds) - kRadius + 5, CGRectGetMidY(self.bounds))];
    [path addLineToPoint:CGPointMake(CGRectGetMidX(self.bounds) - kRadius / 5, CGRectGetMidY(self.bounds) + kRadius / 5 * 2)];
    [path addLineToPoint:CGPointMake(CGRectGetMidX(self.bounds) + kRadius - kRadius / 8 * 3, CGRectGetMidY(self.bounds) - kRadius / 2)];
    
    self.checkLine.path = path.CGPath;
    self.checkLine.lineWidth = kLineWidth;
    self.checkLine.strokeColor = [UIColor colorWithHexString:@"#F98680"].CGColor;
    self.checkLine.fillColor = nil;
    
    //SS(strokeStart)
    CGFloat SSFrom = 0;
    CGFloat SSTo = 1.0;
    // animation
    CABasicAnimation *startAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
    startAnimation.fromValue = @(SSFrom);
    startAnimation.toValue = @(SSTo);
    
    CABasicAnimation *endAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    endAnimation.fromValue = @(SSFrom);
    endAnimation.toValue = @(SSTo);
    
    
    CAAnimationGroup *step2 = [CAAnimationGroup animation];
    step2.animations = @[endAnimation];
    step2.duration = kStep2Duration;
    step2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    
    [self.checkLine addAnimation:step2 forKey:nil];
}
#pragma mark - error

- (void)doErrorStep1 {
    self.arcMoveLayer = [CCArcMoveLayer layer];
    self.arcMoveLayer.contentsScale = [UIScreen mainScreen].scale;
    self.arcMoveLayer.bounds = CGRectMake(0, 0, kRadius * 2 + kLineWidth, kRadius * 2 + kLineWidth);
    self.arcMoveLayer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
    
    // animation
    self.arcMoveLayer.progress = 1; // end status
    [self.layer addSublayer:self.arcMoveLayer];
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"progress"];
    animation.duration = kStep1Duration;
    animation.fromValue = @0.0;
    animation.toValue = @1.0;
    animation.delegate = self;
    [animation setValue:@"errorStep1" forKey:kName];
    [self.arcMoveLayer addAnimation:animation forKey:nil];
}

#pragma mark - success
//成功 第2阶段
- (void)doErrorStep2 {
    self.checkLine = [CAShapeLayer layer];
    [self.layer addSublayer:self.checkLine];
    self.checkLine.frame = self.layer.bounds;
    // path
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    path.lineCapStyle = kCGLineCapSquare; //线条拐角
    path.lineJoinStyle = kCGLineCapRound; //终点处理
    
    [path moveToPoint:CGPointMake(self.frame.size.width/4  + 3, self.frame.size.width/4  + 3  )];
    CGPoint pl =CGPointMake(self.frame.size.width/4*3 - 3, self.frame.size.width/4*3 - 3);
    [path addLineToPoint:pl];

    [path moveToPoint:CGPointMake(self.frame.size.width/4*3 - 3, self.frame.size.width/4 + 3)];

    CGPoint p2 = CGPointMake(self.frame.size.width/4.0 + 3 , self.frame.size.width/4*3 - 3);
    [path addLineToPoint:p2];
    
    self.checkLine.path = path.CGPath;
    self.checkLine.lineWidth = kLineWidth;
    self.checkLine.strokeColor = [UIColor colorWithHexString:@"#F98680"].CGColor;
    self.checkLine.fillColor = nil;
    
    //SS(strokeStart)
    CGFloat SSFrom = 0;
    CGFloat SSTo = 1.0;
    // animation
    CABasicAnimation *startAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
    startAnimation.fromValue = @(SSFrom);
    startAnimation.toValue = @(SSTo);
    
    CABasicAnimation *endAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    endAnimation.fromValue = @(SSFrom);
    endAnimation.toValue = @(SSTo);
    
    
    CAAnimationGroup *step2 = [CAAnimationGroup animation];
    step2.animations = @[endAnimation];
    step2.duration = kStep2Duration;
    step2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    
    [self.checkLine addAnimation:step2 forKey:nil];
}

@end

下面是CCArcMoveLayer.h文件


#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

@interface CCArcMoveLayer : CALayer

@property (nonatomic) CGFloat progress; // 参数
@property (nonatomic) BOOL isSuccess;

@end

下面是CCArcMoveLayer.m文件


#import "CCArcMoveLayer.h"

static CGFloat const kLineWidth = 3;

@interface CCArcMoveLayer ()

@end

@implementation CCArcMoveLayer
@dynamic progress;

+ (BOOL)needsDisplayForKey:(NSString *)key {
    if ([key isEqualToString:@"progress"]) {
        return YES;
    }
    return [super needsDisplayForKey:key];
}

- (void)drawInContext:(CGContextRef)ctx {
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    CGFloat kRadius = MIN(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)) / 2 - kLineWidth / 2;
    CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
    // 0
    CGFloat originStart = M_PI * 3;
    CGFloat originEnd = M_PI * 3;
    CGFloat currentOrigin = originStart - (originStart - originEnd) * self.progress;
    
    // D
    CGFloat destStart = M_PI * 3;
    CGFloat destEnd = 0;
    CGFloat currentDest = destStart - (destStart - destEnd) * self.progress;
    
    [path addArcWithCenter:center radius:kRadius startAngle:currentOrigin endAngle:currentDest clockwise:NO];
    CGContextAddPath(ctx, path.CGPath);
    CGContextSetLineWidth(ctx, kLineWidth);
    CGContextSetStrokeColorWithColor(ctx, [UIColor colorWithHexString:@"#F98680"].CGColor);
//    if (_isSuccess == YES) {
//
//    } else {
//        CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
//    }
    CGContextStrokePath(ctx);
}

@end

那如何使用呢?

    _animationView = [[AnimationView alloc]initWithFrame:CGRectMake(0, 0, 50, 50)];
    [_tipView addSubview:_animationView];

- (IBAction)againAction:(id)sender {
    [self.animationView startSuccessAnimation];
}

- (IBAction)payFinishAction:(id)sender {
    [self.animationView startErrorAnimation];
}

下载链接:

https://download.csdn.net/download/WangQingLei0307/12610141

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王 哪跑!!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值