如何在CALayer中为UIColor设置动画?

时间:2018-10-09 18:46:43

标签: ios objective-c core-graphics core-animation calayer

我有一个自定义CALayer,我试图在其中使用actionForKey并在this tutorial之后启用某些属性的动画。

我有一个CGFloat属性,当在动画块中时,该属性会发生完美变化,而我的另一个属性UIColor则不会。

这是我的职能:

- (id<CAAction>)actionForKey:(NSString *)event {

    if ([self presentationLayer] != nil && [[self class] isCustomAnimationKey:event]) {
        id animation = [super actionForKey:@"backgroundColor"];
        if (animation == nil || [animation isEqual:[NSNull null]]) {
            [self setNeedsDisplay];
            return [NSNull null];
        }
        [animation setKeyPath:event];
        [animation setFromValue:[self.presentationLayer valueForKey:event]];
        [animation setToValue:nil];
        return animation;
    }
    return [super actionForKey:event];
}

正在使用CGContextSetFillColorWithColor设置颜色,但是我从日志中看到,颜色只是从一种颜色更改为另一种颜色,而没有任何内插值。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

最后发现很明显,我需要在CALayer中公开一个CGColor属性,并对其进行动画处理。

编辑:

这里有一些代码,以UIViewCustomPropertyAnimation项目为基础。

OCLayer.h中添加新属性:

@property (nonatomic) CGColorRef myColor;

OCLayer.m中添加@dynamic指令:

@dynamic myColor;

并更新isCustomAnimKey

+ (BOOL)isCustomAnimKey:(NSString *)key {
    return [key isEqualToString:@"percent"] || [key isEqualToString:@"myColor"];
}

OCView.h中添加相同的属性,但将其作为UIColor。这已经存在于我的项目中,因此不需要修改,这很棒,因为它没有破坏任何代码。

@property (nonatomic, strong) UIColor *progressColor;

主要更改将在OCView.m中,因为获取器和设置器需要从CGColor转换为UIColor,然后再次返回。

- (void)setMyColor:(UIColor *)color {
    self.layer.myColor = color.CGColor;
}

- (UIColor*)myColor {
    return [UIColor colorWithCGColor: self.layer.myColor];
}

现在可以正常执行动画了:

[UIView animateWithDuration:1.f animations:^{
    self.animView.myColor = [UIColor redColor];
}];

答案 1 :(得分:0)

这是我的代码,而不是答案。共有三类:OCLayer,OCView和OCViewController。您可以看到动画期间“百分比”的值正在变化,而“ myColor”的值却没有变化。

@interface OCLayer : CALayer
@property (nonatomic) CGFloat  percent;
@property (nonatomic) CGColorRef myColor;
@end


#import "OCLayer.h"
@implementation OCLayer
@dynamic percent;
@dynamic myColor;

- (id<CAAction>)actionForKey:(NSString *)key
{
if ([[self class] isCustomAnimKey:key])
{
    id animation = [super actionForKey:@"backgroundColor"];
    if (animation == nil || [animation isEqual:[NSNull null]])
    {
        [self setNeedsDisplay];
        return [NSNull null];
    }
    [animation setKeyPath:key];
    [animation setFromValue:   [self.presentationLayer valueForKey:key]];
        [animation setToValue : nil];
    return animation;
}
return [super actionForKey:key];
}


- (id)initWithLayer:(id)layer
{
self = [super initWithLayer:layer];
if (self)
{
    if ([layer isKindOfClass:[OCLayer class]])
    {
        self.percent = ((OCLayer *)layer).percent;
    }
}
return self;
}

+ (BOOL)needsDisplayForKey:(NSString *)key
{
 if ([self isCustomAnimKey:key]) return true;
 return [super needsDisplayForKey:key];
}

+ (BOOL)isCustomAnimKey:(NSString *)key
 {
  return [key isEqualToString:@"percent"] || [key isEqualToString:@"myColor"];
 }
 @end


@interface OCView : UIView
@property (weak, nonatomic) IBOutlet UIView *percentView;
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (nonatomic, strong) UIColor * myColor;

//- (UIColor*)myColor ;
//- (void)setMyColor:(UIColor *)color;
- (CGFloat )percent;
- (void)setPercent:(CGFloat )percent;
@end


    #import "OCView.h"
    #import "OCLayer.h"

    @implementation OCView

    - (void)displayLayer:(CALayer *)layer
    {
        CGFloat percent = [(OCLayer *)[self.layer presentationLayer] percent];

        CGColorRef myColor = [(OCLayer *)[self.layer presentationLayer] myColor];
        NSLog(@"%f", percent);
        NSLog(@"%@", myColor);

        self.percentView.backgroundColor = [[UIColor alloc]initWithCGColor: myColor];
        self.label.text = [NSString stringWithFormat:@"%.0f", floorf(percent)];
    }

    + (Class)layerClass
    {
        return [OCLayer class];
    }

    - (void)setPercent:( CGFloat )percent
    {
        ((OCLayer *)self.layer).percent = percent;
    }

    - (CGFloat )percent
    {
        return ((OCLayer *)self.layer).percent;
    }


    - (void)setMyColor:(UIColor *)color {
        ((OCLayer *)self.layer).myColor = color.CGColor;
    }

    - (UIColor*)myColor {
        return [UIColor colorWithCGColor:  ((OCLayer *)self.layer).myColor];
    }
  @end


   @interface OCViewController : UIViewController
    @property (weak, nonatomic) IBOutlet OCView *animView;

    @end



    #import "OCViewController.h"
    #import "OCLayer.h"
    @interface OCViewController ()
    @end

    @implementation OCViewController
    -(void)viewDidAppear:(BOOL)animated{
        [super viewDidAppear:animated];
        self.animView.percent = 1;
        self.animView.myColor = [UIColor whiteColor];
        [UIView animateWithDuration:3.0
                         animations:^{
                               self.animView.percent = 20;
                               self.animView.myColor = [UIColor redColor];
                         }];



    }
    - (void)viewDidLoad {
        [super viewDidLoad];

    }
 @end