iOS 自定义View动画(needsDisplayForKey、setNeedsDisplay应用)

实现自定义View ,有两种办法:

1、 view上实现

-(void)drawRect:(CGRect)rect;

2、layer上实现

-(void)drawInContext:(CGContextRef)ctx;

方法一:View的drawRect应用

例子:画圆弧

@interface CircleProgressView : UIView
@property (nonatomic, assign) CGFloat progress;
@end
- (void)drawRect:(CGRect)rect {    
    CGFloat radius = self.bounds.size.width / 2;    
    CGFloat lineWidth = 10.0;    
    UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius - lineWidth / 2 startAngle:0.f endAngle:M_PI * 2 * self.progress clockwise:YES];    
    [[UIColor colorWithRed:0.5 green:0.5 blue:0.9 alpha:1.0] setStroke];    
    [path setLineWidth:lineWidth];   
    [path stroke];
}
-(void)viewDidLoad {    
    [super viewDidLoad];      
    self.circleProgressView = [[CircleProgressView alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];    
    [self.view addSubview:self.circleProgressView];
}
// 控制progress的值到达动画效果
-(void)controlProgressAnimation{
  self.circleProgressView.progress = random();
  [self.circleProgressView setNeedsDisplay];
}

方法二:layer的drawInContext应用

例子:画圆弧

CircleProgressLayer.h 添加 progress属性

@interface CircleProgressLayer : CALayer
@property (nonatomic, assign) CGFloat progress;
@end

1.重载initWithLayer方法

- (instancetype)initWithLayer:(CircleProgressLayer *)layer {    
    NSLog(@"initLayer");    
    if (self = [super initWithLayer:layer]) {        
        self.progress = layer.progress;    
    }    
    return self;
}

2.重载其绘图方法 drawInContext

- (void)drawInContext:(CGContextRef)ctx {    
    CGFloat radius = self.bounds.size.width / 2;    
    CGFloat lineWidth = 10.0;    
    UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius - lineWidth / 2 startAngle:0.f endAngle:M_PI * 2 * self.progress clockwise:YES];    
    CGContextSetRGBStrokeColor(ctx, 0.5, 0.5, 0.9, 1.0);//笔颜色    
    CGContextSetLineWidth(ctx, 10);//线条宽度    
    CGContextAddPath(ctx, path.CGPath);    
    CGContextStrokePath(ctx);
}

3.progress属性变化时让其自动重绘

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

4.view中使用

-(id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.circleProgressLayer = [CircleProgressLayer layer];
        self.circleProgressLayer.frame = self.bounds;
        //像素大小比例
        self.circleProgressLayer.contentsScale = [UIScreen mainScreen].scale;
        [self.layer addSublayer:self.circleProgressLayer];
    }
    return self;
}
-(void)setProgress:(CGFloat)progress {
    CABasicAnimation * ani = [CABasicAnimation animationWithKeyPath:@"progress"];
    ani.duration = 5.0 * fabs(progress - _progress);
    ani.toValue = @(progress);
    ani.removedOnCompletion = YES;
    ani.fillMode = kCAFillModeForwards;
    ani.delegate = self;
    [self.circleProgressLayer addAnimation:ani forKey:@"progressAni"];
    _progress = progress;
}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    self.circleProgressLayer.progress = self.progress;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 前言 在上一篇文章iOS动画篇:自定义View中讲到了如何在view里画一个圆,本文将在此基础上给其加上弧度变化的...
    明仔Su阅读 11,734评论 10 43
  • 转载:http://www.jianshu.com/p/32fcadd12108 每个UIView有一个伙伴称为l...
    F麦子阅读 11,524评论 0 13
  • 每个UIView有一个伙伴称为layer,一个CALayer。UIView实际上并没有把自己画到屏幕上;它绘制本身...
    shenzhenboy阅读 8,356评论 0 17
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 12,733评论 6 30
  • 我的恐惧清单: 事业 1,害怕老板批评 2,害怕承担出错带来的责任 3,害怕工作被人取代 人际 4,害怕和不熟悉的...
    joylulu阅读 1,688评论 0 0

友情链接更多精彩内容