Fill Color Animation Мерцает, когда вызывается блок в анимации

У меня проблемы с выяснением, почему анимация мигает от fromValue к toValue после завершения моего блока анимации. Я знаю, что после завершения анимации вы должны установить значения CALayer в конечное состояние анимации, чтобы она выглядела согласованно. Тем не менее, независимо от того, в каком порядке я вызываю эти методы, я продолжаю получать мерцающий результат. То, что я делаю, это рисование галочки с помощью контура Biezer, а затем, когда анимация strokeEnd завершена, я заполняю галочку, анимируя свойство fillColor. Функция заполнения галочки и функция сброса галочки запускаются, когда пользователь выбирает строку ячейки табличного просмотра, с которой связана галочка. Да, и я использую AutoLayout, если это имеет значение.

Итак, мне интересно несколько вещей на самом деле: 1) Как только ячейка табличного представления отображается, я вызываю публичную функцию shoudSetCheckmarkToCheckedState, которая устанавливает логическое значение self.userSelectedCheckmark для параметра isChecked, передаваемого в функцию. Оттуда я вызываю [self setNeedsLayout], который запускает layoutSubviews и вызывает функцию shouldDrawCheckmark .... Причина, по которой я это делаю, заключается в том, что если я не делаю первый раз, когда ячейка рисуется, рамка не устанавливается, поэтому мой рисунок выглядит беспорядочно. Поэтому я должен вызывать setNeedsLayout каждый раз, когда я изменяю свойство userSelectedCheckmark или есть лучший способ.

2) Почему флажок мигает после завершения анимации. Я думаю, я знаю почему, потому что, когда анимация завершается, свойства слоев сбрасываются в то же состояние, в котором они находились, когда слой начал анимироваться. Итак, как я могу это исправить? Я бы просто включил таймер, чтобы изменить цвет заливки за миллисекунду до окончания анимации, но это не так.

вот код между прочим

typedef void (^animationCompletionBlock)(void);
#define kAnimationCompletionBlock @"animationCompletionBlock"

#import "CheckmarkView.h"
#import "UIColor+HexString.h"

@interface CheckmarkView()
@property (nonatomic,strong) CAShapeLayer *checkmarkLayer;
@property (nonatomic,assign) BOOL userSelectedCheckmark;
- (void)shouldDrawCheckmarkToLayerWithAnimation:(BOOL)animateCheckmark;
@end

@implementation CheckmarkView

#pragma mark - Lifecycle
/**********************/
- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.translatesAutoresizingMaskIntoConstraints = FALSE;
        self.layer.cornerRadius = 5.0;
        [self setClipsToBounds:TRUE];
    }
    return self;
}
- (void)layoutSubviews{
   [self shouldDrawCheckmarkToLayerWithAnimation:self.userSelectedCheckmark];
}

#pragma mark - Public Methods
/***************************/
- (void)shouldSetCheckmarkToCheckedState:(BOOL)isChecked{
    self.userSelectedCheckmark = isChecked;
    [self setNeedsLayout];
}

#pragma mark - Private Methods
/****************************/
- (void)shouldDrawCheckmarkToLayerWithAnimation:(BOOL)animateCheckmark{

    if(self.userSelectedCheckmark){

        CGRect superlayerRect = self.bounds;
        if(!self.checkmarkLayer){

            self.checkmarkLayer = [CAShapeLayer layer];
            [self.checkmarkLayer setStrokeColor:[UIColor whiteColor].CGColor];

            UIBezierPath *checkMarkPath = [UIBezierPath bezierPath];
            //Start Point
            [checkMarkPath moveToPoint:CGPointMake(CGRectGetMinX(superlayerRect) + 5, CGRectGetMinY(superlayerRect) + 14)];

            //Bottom Point
            [checkMarkPath addLineToPoint:CGPointMake(CGRectGetMidX(superlayerRect), CGRectGetMaxY(superlayerRect) - 4)];

            //Top Right of self.checkmarkLayer
            [checkMarkPath addLineToPoint:CGPointMake(CGRectGetMaxX(superlayerRect) - 5, CGRectGetMinY(superlayerRect) + 8)];
            [checkMarkPath addLineToPoint:CGPointMake(checkMarkPath.currentPoint.x - 3, checkMarkPath.currentPoint.y - 4)];

            //Top Middle Point
            [checkMarkPath addLineToPoint:CGPointMake(CGRectGetMidX(superlayerRect) - 1, CGRectGetMidY(superlayerRect) + 2)];

            //Top left of self.checkmarkLayer
            [checkMarkPath addLineToPoint:CGPointMake(CGRectGetMinX(superlayerRect) + 7, CGRectGetMinY(superlayerRect) + 10)];
            [checkMarkPath closePath];
            [self.checkmarkLayer setPath:checkMarkPath.CGPath];
        }

        self.layer.backgroundColor = [UIColor colorWithHexString:UIColorOrangeB0].CGColor;
        [self.checkmarkLayer setFillColor:[UIColor colorWithHexString:UIColorOrangeB0].CGColor];
        [self.layer addSublayer:self.checkmarkLayer];

        if(animateCheckmark){

            animationCompletionBlock block;
            block = ^(void){
                [self.checkmarkLayer setFillColor:[UIColor whiteColor].CGColor];
            };

            CABasicAnimation *strokeAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
            [strokeAnimation setBeginTime:0.0];
            [strokeAnimation setFromValue:@(0.0f)];
            [strokeAnimation setToValue:@(1.0f)];
            [strokeAnimation setDuration:.8];

            CABasicAnimation *fillAnimation = [CABasicAnimation animationWithKeyPath:@"fillColor"];
            [fillAnimation setBeginTime:strokeAnimation.duration + .2];
            [fillAnimation setDuration:.2];
            [fillAnimation setFromValue:(id)[UIColor colorWithHexString:UIColorOrangeB0].CGColor];
            [fillAnimation setToValue:(id)[UIColor whiteColor].CGColor];

            CAAnimationGroup *group = [CAAnimationGroup animation];
            group.delegate = self;
            [group setDuration:1.5];
            [group setAnimations:@[strokeAnimation,fillAnimation]];
            [group setValue:block forKey:kAnimationCompletionBlock];
            [self.checkmarkLayer addAnimation:group forKey:nil];
        }
    }
    else{
        self.layer.backgroundColor = [UIColor colorWithHexString:UIColorWhiteOffset].CGColor;
        [self.checkmarkLayer setFillColor:[UIColor colorWithHexString:UIColorOrangeB0].CGColor];
        [self.checkmarkLayer removeFromSuperlayer];
    }

}


#pragma mark - CAAnimationBlock
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
    animationCompletionBlock theBlock = [theAnimation valueForKey: kAnimationCompletionBlock];
    if (theBlock)
        theBlock();
}

Ответы на вопрос(1)

Ваш ответ на вопрос