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();
}