Как я могу оживить UIColor в CALayer? - PullRequest
0 голосов
/ 09 октября 2018

У меня есть пользовательский CALayer, в котором я пытаюсь включить анимацию определенных свойств, используя actionForKey и следуя этому уроку .

У меня есть *Свойство 1007 *, которое будет отлично меняться, когда внутри блока анимации, но мое другое свойство, 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 голосов
/ 10 октября 2018

Это мой код, а не ответ.Существует три класса: 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
0 голосов
/ 10 октября 2018

В конце концов это оказалось очевидным, мне нужно было выставить свойство CGColor в моем CALayer и анимировать его вместо этого.

Edit:

Вот код для этого,используя 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];
}];
...