Skip to content
This repository has been archived by the owner on Aug 25, 2023. It is now read-only.

Feature/checkbox update #15

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@

@interface MLCheckBox : MLBooleanWidget

- (void)setEnabled:(BOOL)enabled Animated:(BOOL)animated;

@end
194 changes: 90 additions & 104 deletions LibraryComponents/MLBooleanWidget/MLCheckBox/classes/MLCheckBox.m
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,49 @@ - (void)layoutSubviews
self.checkBoxInternalLayer.frame = self.bounds;
}

#pragma mark - Public Methods
- (void)setEnabled:(BOOL)enabled Animated:(BOOL)animated
{
if (self.userInteractionEnabled == enabled) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usaría un Bool propio del checkbox para mantener el estado enabled/disabled. Nadie te debería modificar el userInteractionEnabled pero podrían y el estado de la ui quedaría raro.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lo que me causa un toque de duda ahí es que si no estoy cambiando el userInteractionEnabled, es posible que la interacción con el componente siga siendo manejada desde BooleanWidget. Lo voy a probar

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahí lo probé y parece andar bien. Voy a commitear un cambio con una property BOOL isEnabled

return;
}

self.userInteractionEnabled = enabled;
if (enabled) {
if (self.isBooleanWidgetOn) {
[self fillCheckBoxExternalFromColor:[UIColor ml_meli_mid_grey] ToColor:[UIColor ml_meli_blue] Animated:animated];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Movería los [UIColor ...] a funciones que devuelvan el color para cada estado (checkboxColorOn, checkboxColorOff y checkboxColorDisabled). Así se actualizan desde un solo lugar en caso de querer cambiar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claro, yo lo dejé así pero en el fondo estaba pensando que estaría bueno que haya algún config de colores en el futuro. Lo voy a armar con dos métodos así está un pasito más cerca a tener los colores configurables.

[self fillCheckBoxInternalFromColor:[UIColor ml_meli_mid_grey] ToColor:[UIColor ml_meli_blue] FromOpacity:1 ToOpacity:1 Animated:animated];
[self fillCheckBoxTickAnimated:animated];
} else {
[self fillCheckBoxExternalFromColor:[UIColor ml_meli_mid_grey] ToColor:[UIColor ml_meli_grey] Animated:animated];
[self fillCheckBoxInternalFromColor:[UIColor ml_meli_mid_grey] ToColor:[UIColor ml_meli_grey] FromOpacity:0 ToOpacity:0 Animated:animated];
}
} else {
if (self.isBooleanWidgetOn) {
[self fillCheckBoxExternalFromColor:[UIColor ml_meli_blue] ToColor:[UIColor ml_meli_mid_grey] Animated:animated];
[self fillCheckBoxInternalFromColor:[UIColor ml_meli_blue] ToColor:[UIColor ml_meli_mid_grey] FromOpacity:1 ToOpacity:1 Animated:animated];
[self fillCheckBoxTickAnimated:animated];
} else {
[self fillCheckBoxExternalFromColor:[UIColor ml_meli_grey] ToColor:[UIColor ml_meli_mid_grey] Animated:animated];
[self fillCheckBoxInternalFromColor:[UIColor ml_meli_grey] ToColor:[UIColor ml_meli_mid_grey] FromOpacity:0 ToOpacity:0 Animated:animated];
}
}
}

#pragma mark - Animation

- (void)setOnBooleanWidgetAnimated:(BOOL)animated
{
if (self.isBooleanWidgetOn) {
return;
}

[self fillCheckBoxExternalAnimated:animated];
[self fillCheckBoxInternalAnimated:animated];
[self fillCheckBoxInternalFromColor:[UIColor ml_meli_grey] ToColor:[UIColor ml_meli_blue] FromOpacity:0 ToOpacity:1 Animated:animated];
[self fillCheckBoxTickAnimated:animated];
}

- (void)fillCheckBoxExternalAnimated:(BOOL)animated
- (void)fillCheckBoxExternalFromColor:(UIColor *)fromColor ToColor:(UIColor *)toColor Animated:(BOOL)animated
{
// Set circle layer bounds
self.checkBoxExternalLayer.bounds = CGRectMake(0, 0, CGRectGetHeight(self.frame), CGRectGetWidth(self.frame));
Expand All @@ -82,52 +112,40 @@ - (void)fillCheckBoxExternalAnimated:(BOOL)animated
self.checkBoxExternalLayer.path = externalFrame.CGPath;

self.checkBoxExternalLayer.fillColor = [UIColor clearColor].CGColor;
float lineWidth = kMLCheckBoxExternalLineWidth;

self.checkBoxExternalLayer.lineWidth = lineWidth;
self.checkBoxExternalLayer.lineWidth = kMLCheckBoxExternalLineWidth;

// Color animation
CABasicAnimation *colorFillAnimation = [CABasicAnimation animationWithKeyPath:@"strokeColor"];
colorFillAnimation.beginTime = 0;
colorFillAnimation.fromValue = (id)[UIColor ml_meli_grey].CGColor;
colorFillAnimation.toValue = (id)[UIColor ml_meli_blue].CGColor;
colorFillAnimation.fillMode = kCAFillModeForwards;
colorFillAnimation.duration = animated ? kMLCheckBoxAnimationDuration : kMLCheckBoxNotAnimationDuration;
CABasicAnimation *colorFillAnimation = [self createColorFillAnimationFromColor:fromColor ToColor:toColor WithDuration:animated ? kMLCheckBoxAnimationDuration : kMLCheckBoxNotAnimationDuration];

[self.checkBoxExternalLayer addAnimation:colorFillAnimation forKey:@"animateFill"];

self.checkBoxExternalLayer.strokeColor = [UIColor ml_meli_blue].CGColor;
self.checkBoxExternalLayer.strokeColor = toColor.CGColor;
}

- (void)fillCheckBoxExternalAnimated:(BOOL)animated
{
[self fillCheckBoxExternalFromColor:[UIColor ml_meli_grey] ToColor:[UIColor ml_meli_blue] Animated:animated];
}

- (void)fillCheckBoxInternalAnimated:(BOOL)animated
- (void)fillCheckBoxInternalFromColor:(UIColor *)fromColor ToColor:(UIColor *)toColor FromOpacity:(float)fromOpacity ToOpacity:(float)toOpacity Animated:(BOOL)animated
{
// Set circle layer bounds
self.checkBoxInternalLayer.bounds = CGRectMake(0, 0, CGRectGetHeight(self.frame), CGRectGetWidth(self.frame));

// Set circle layer path
UIBezierPath *externalFrame = [UIBezierPath bezierPathWithRoundedRect:self.checkBoxExternalLayer.bounds cornerRadius:kMLCheckBoxExternalCornerRadius];
self.checkBoxInternalLayer.path = externalFrame.CGPath;

UIBezierPath *internalFrame = [UIBezierPath bezierPathWithRoundedRect:self.checkBoxExternalLayer.bounds cornerRadius:kMLCheckBoxExternalCornerRadius];
self.checkBoxInternalLayer.path = internalFrame.CGPath;

self.checkBoxInternalLayer.fillColor = [UIColor ml_meli_blue].CGColor;
self.checkBoxInternalLayer.fillColor = toOpacity == 0 ? [UIColor clearColor].CGColor : toColor.CGColor;
float lineWidth = kMLCheckBoxExternalLineWidth;

self.checkBoxInternalLayer.lineWidth = lineWidth;

// Opacity animation
CABasicAnimation *opacityFillAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityFillAnimation.beginTime = 0;
opacityFillAnimation.fromValue = @0;
opacityFillAnimation.toValue = @1;
opacityFillAnimation.fillMode = kCAFillModeForwards;
CABasicAnimation *opacityFillAnimation = [self createOpacityFillAnimationFromValue:fromOpacity ToValue:toOpacity];

// Color animation
CABasicAnimation *colorFillAnimation = [CABasicAnimation animationWithKeyPath:@"strokeColor"];
colorFillAnimation.beginTime = 0;
colorFillAnimation.fromValue = (id)[UIColor ml_meli_grey].CGColor;
colorFillAnimation.toValue = (id)[UIColor ml_meli_blue].CGColor;
colorFillAnimation.fillMode = kCAFillModeForwards;
CABasicAnimation *colorFillAnimation = [self createColorFillAnimationFromColor:fromColor ToColor:toColor];

// Compaund animation
CAAnimationGroup *fillAnimation = [CAAnimationGroup animation];
Expand All @@ -136,9 +154,7 @@ - (void)fillCheckBoxInternalAnimated:(BOOL)animated

[self.checkBoxInternalLayer addAnimation:fillAnimation forKey:@"animateFill"];

self.checkBoxInternalLayer.strokeColor = [UIColor ml_meli_blue].CGColor;
self.checkBoxInternalLayer.path = internalFrame.CGPath;
self.checkBoxInternalLayer.opacity = 1;
self.checkBoxInternalLayer.strokeColor = toColor.CGColor;
}

- (void)fillCheckBoxTickAnimated:(BOOL)animated
Expand All @@ -163,7 +179,6 @@ - (void)fillCheckBoxTickAnimated:(BOOL)animated

// Color animation
CABasicAnimation *pathTickAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathTickAnimation.beginTime = 0;
pathTickAnimation.fromValue = @0.0;
pathTickAnimation.toValue = @1.0;
pathTickAnimation.fillMode = kCAFillModeForwards;
Expand All @@ -174,79 +189,8 @@ - (void)fillCheckBoxTickAnimated:(BOOL)animated

- (void)setOffBooleanWidgetAnimated:(BOOL)animated
{
[self clearCheckBoxExternalAnimated:animated];
[self clearCheckBoxInternalAnimated:animated];
}

- (void)clearCheckBoxExternalAnimated:(BOOL)animated
{
// Set circle layer bounds
self.checkBoxExternalLayer.bounds = CGRectMake(0, 0, CGRectGetHeight(self.frame), CGRectGetWidth(self.frame));

// Set circle layer path
UIBezierPath *externalFrame = [UIBezierPath bezierPathWithRoundedRect:self.checkBoxExternalLayer.bounds cornerRadius:kMLCheckBoxExternalCornerRadius];

self.checkBoxExternalLayer.path = externalFrame.CGPath;

self.checkBoxExternalLayer.fillColor = [UIColor clearColor].CGColor;
float lineWidth = kMLCheckBoxExternalLineWidth;

self.checkBoxExternalLayer.lineWidth = lineWidth;

// Color animation
CABasicAnimation *colorFillAnimation = [CABasicAnimation animationWithKeyPath:@"strokeColor"];
colorFillAnimation.beginTime = 0;
colorFillAnimation.fromValue = (id)[UIColor ml_meli_blue].CGColor;
colorFillAnimation.toValue = (id)[UIColor ml_meli_grey].CGColor;
colorFillAnimation.fillMode = kCAFillModeForwards;
colorFillAnimation.duration = animated ? kMLCheckBoxAnimationDuration : kMLCheckBoxNotAnimationDuration;

[self.checkBoxExternalLayer addAnimation:colorFillAnimation forKey:@"animateFill"];

self.checkBoxExternalLayer.strokeColor = [UIColor ml_meli_grey].CGColor;
}

- (void)clearCheckBoxInternalAnimated:(BOOL)animated
{
// Set circle layer bounds
self.checkBoxInternalLayer.bounds = CGRectMake(0, 0, CGRectGetHeight(self.frame), CGRectGetWidth(self.frame));

// Set circle layer path
UIBezierPath *externalFrame = [UIBezierPath bezierPathWithRoundedRect:self.checkBoxExternalLayer.bounds cornerRadius:kMLCheckBoxExternalCornerRadius];

UIBezierPath *internalFrame = [UIBezierPath bezierPathWithRoundedRect:self.checkBoxExternalLayer.bounds cornerRadius:kMLCheckBoxExternalCornerRadius];
[internalFrame fill];

self.checkBoxInternalLayer.path = internalFrame.CGPath;

self.checkBoxInternalLayer.fillColor = [UIColor clearColor].CGColor;
float lineWidth = kMLCheckBoxExternalLineWidth;
self.checkBoxInternalLayer.lineWidth = lineWidth;

// Opacity animation
CABasicAnimation *opacityClearAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityClearAnimation.beginTime = 0;
opacityClearAnimation.fromValue = @1;
opacityClearAnimation.toValue = @0;
opacityClearAnimation.fillMode = kCAFillModeForwards;

// Color animation
CABasicAnimation *colorClearAnimation = [CABasicAnimation animationWithKeyPath:@"strokeColor"];
colorClearAnimation.beginTime = 0;
colorClearAnimation.fromValue = (id)[UIColor ml_meli_blue].CGColor;
colorClearAnimation.toValue = (id)[UIColor ml_meli_grey].CGColor;
colorClearAnimation.fillMode = kCAFillModeForwards;

// Compaund animation
CAAnimationGroup *clearAnimation = [CAAnimationGroup animation];
clearAnimation.duration = animated ? kMLCheckBoxAnimationDuration : kMLCheckBoxNotAnimationDuration;
[clearAnimation setAnimations:[NSArray arrayWithObjects:colorClearAnimation, opacityClearAnimation, nil]];

[self.checkBoxInternalLayer addAnimation:clearAnimation forKey:@"animateClear"];

self.checkBoxInternalLayer.strokeColor = [UIColor ml_meli_grey].CGColor;
self.checkBoxInternalLayer.path = externalFrame.CGPath;
self.checkBoxInternalLayer.opacity = 0;
[self fillCheckBoxExternalFromColor:[UIColor ml_meli_blue] ToColor:[UIColor ml_meli_grey] Animated:animated];
[self fillCheckBoxInternalFromColor:[UIColor ml_meli_blue] ToColor:[UIColor ml_meli_grey] FromOpacity:1 ToOpacity:0 Animated:animated];
}

#pragma mark - Tick Positions
Expand Down Expand Up @@ -274,4 +218,46 @@ - (CGPoint)tickRightPointInRect:(CGRect)rect
return CGPointMake(x, y);
}

- (CABasicAnimation *)createOpacityFillAnimationFromValue:(float)fromValue ToValue:(float)toValue
{
return [self createOpacityFillAnimationFromValue:fromValue ToValue:toValue WithDuration:0 WithFillMode:kCAFillModeForwards];
}

- (CABasicAnimation *)createOpacityFillAnimationFromValue:(float)fromValue ToValue:(float)toValue WithDuration:(double)duration
{
return [self createOpacityFillAnimationFromValue:fromValue ToValue:toValue WithDuration:duration WithFillMode:kCAFillModeForwards];
}

- (CABasicAnimation *)createOpacityFillAnimationFromValue:(float)fromValue ToValue:(float)toValue WithDuration:(double)duration WithFillMode:(NSString *)fillMode
{
CABasicAnimation *opacityFillAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityFillAnimation.fromValue = [NSNumber numberWithFloat:fromValue];
opacityFillAnimation.toValue = [NSNumber numberWithFloat:toValue];
opacityFillAnimation.duration = duration;
opacityFillAnimation.fillMode = fillMode;

return opacityFillAnimation;
}

- (CABasicAnimation *)createColorFillAnimationFromColor:(UIColor *)fromColor ToColor:(UIColor *)toColor WithDuration:(double)duration
{
return [self createColorFillAnimationFromColor:fromColor ToColor:toColor WithDuration:duration WithFillMode:kCAFillModeForwards];
}

- (CABasicAnimation *)createColorFillAnimationFromColor:(UIColor *)fromColor ToColor:(UIColor *)toColor
{
return [self createColorFillAnimationFromColor:fromColor ToColor:toColor WithDuration:0 WithFillMode:kCAFillModeForwards];
}

- (CABasicAnimation *)createColorFillAnimationFromColor:(UIColor *)fromColor ToColor:(UIColor *)toColor WithDuration:(double)duration WithFillMode:(NSString *)fillMode
{
CABasicAnimation *colorFillAnimation = [CABasicAnimation animationWithKeyPath:@"strokeColor"];
colorFillAnimation.fromValue = (id)fromColor.CGColor;
colorFillAnimation.toValue = (id)toColor.CGColor;
colorFillAnimation.duration = duration;
colorFillAnimation.fillMode = fillMode;

return colorFillAnimation;
}

@end