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;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前言 在上一篇文章iOS動畫篇:自定義View中講到了如何在view里畫一個圓,本文將在此基礎上給其加上弧度變化的...
    明仔Su閱讀 6,684評論 10 43
  • 轉載:http://www.lxweimin.com/p/32fcadd12108 每個UIView有一個伙伴稱為l...
    F麥子閱讀 6,318評論 0 13
  • 每個UIView有一個伙伴稱為layer,一個CALayer。UIView實際上并沒有把自己畫到屏幕上;它繪制本身...
    shenzhenboy閱讀 3,160評論 0 17
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,572評論 6 30
  • 我的恐懼清單: 事業 1,害怕老板批評 2,害怕承擔出錯帶來的責任 3,害怕工作被人取代 人際 4,害怕和不熟悉的...
    joylulu閱讀 235評論 0 0