diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index f09f45b3..527527ab 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -11,6 +11,10 @@ 01DF567021FA5AB300CC099B /* MVMCoreUITextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* MVMCoreUITextFieldListFormViewController.swift */; }; D206997721FB8A0B00CAE0DE /* MVMCoreUINavigationControllerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationControllerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D206997821FB8A0B00CAE0DE /* MVMCoreUINavigationControllerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D206997621FB8A0B00CAE0DE /* MVMCoreUINavigationControllerViewController.m */; }; + D22D1F1A220341F60077CEC0 /* MVMCoreUICheckBox.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F18220341F50077CEC0 /* MVMCoreUICheckBox.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */; }; + D22D1F1E220343560077CEC0 /* MVMCoreUICheckMarkView.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F1C220343560077CEC0 /* MVMCoreUICheckMarkView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F1D220343560077CEC0 /* MVMCoreUICheckMarkView.m */; }; D28B4F8A21FF967C00712C7A /* MVMCoreUIObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D28B4F8821FF967C00712C7A /* MVMCoreUIObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; D28B4F8B21FF967C00712C7A /* MVMCoreUIObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D28B4F8921FF967C00712C7A /* MVMCoreUIObject.m */; }; D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */; }; @@ -152,6 +156,10 @@ 01DF566F21FA5AB300CC099B /* MVMCoreUITextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MVMCoreUITextFieldListFormViewController.swift; sourceTree = ""; }; D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationControllerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUINavigationControllerViewController.h; sourceTree = ""; }; D206997621FB8A0B00CAE0DE /* MVMCoreUINavigationControllerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUINavigationControllerViewController.m; sourceTree = ""; }; + D22D1F18220341F50077CEC0 /* MVMCoreUICheckBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUICheckBox.h; sourceTree = ""; }; + D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUICheckBox.m; sourceTree = ""; }; + D22D1F1C220343560077CEC0 /* MVMCoreUICheckMarkView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUICheckMarkView.h; sourceTree = ""; }; + D22D1F1D220343560077CEC0 /* MVMCoreUICheckMarkView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUICheckMarkView.m; sourceTree = ""; }; D28B4F8821FF967C00712C7A /* MVMCoreUIObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIObject.h; sourceTree = ""; }; D28B4F8921FF967C00712C7A /* MVMCoreUIObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIObject.m; sourceTree = ""; }; D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsView.m; sourceTree = ""; }; @@ -530,6 +538,10 @@ D29DF32221ED0DA2003B2FB9 /* TextButtonView.m */, D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */, D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */, + D22D1F1C220343560077CEC0 /* MVMCoreUICheckMarkView.h */, + D22D1F1D220343560077CEC0 /* MVMCoreUICheckMarkView.m */, + D22D1F18220341F50077CEC0 /* MVMCoreUICheckBox.h */, + D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */, ); path = Views; sourceTree = ""; @@ -659,6 +671,7 @@ D29DF2B021E7B3A4003B2FB9 /* MFTextView.h in Headers */, D29DF2A921E7B2F9003B2FB9 /* MVMCoreUIConstants.h in Headers */, D29DF25221E6A177003B2FB9 /* MFMdnTextField.h in Headers */, + D22D1F1A220341F60077CEC0 /* MVMCoreUICheckBox.h in Headers */, D29DF29921E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h in Headers */, D29DF11C21E684A9003B2FB9 /* MVMCoreUISplitViewController.h in Headers */, D29DF29B21E7ADB9003B2FB9 /* StackableViewController.h in Headers */, @@ -670,6 +683,7 @@ D29DF11521E6805F003B2FB9 /* UIColor+MFConvenience.h in Headers */, D29DF2BC21E7BEA4003B2FB9 /* TopTabbar.h in Headers */, D29DF25921E6A22D003B2FB9 /* MFButtonProtocol.h in Headers */, + D22D1F1E220343560077CEC0 /* MVMCoreUICheckMarkView.h in Headers */, D29DF28421E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h in Headers */, D29DF2CE21E7C104003B2FB9 /* MFLoadingViewController.h in Headers */, D29DF12A21E6851E003B2FB9 /* MVMCoreUITopAlertView.h in Headers */, @@ -801,6 +815,7 @@ D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */, D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, + D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */, D29770F921F7C73800B2F0D0 /* PrimaryButtonView.m in Sources */, @@ -857,6 +872,7 @@ D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */, D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, + D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */, D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */, D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */, ); diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h new file mode 100644 index 00000000..8a9ab067 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h @@ -0,0 +1,61 @@ +// +// MVMCoreUICheckBox.h +// myverizon +// +// Created by Suresh, Kamlesh on 11/25/15. +// Copyright © 2015 Verizon Wireless. All rights reserved. +// + +#import +#import +#import +#import +@class MFSizeObject; + +@interface MVMCoreUICheckBox : UIControl + +@property (nullable, weak, nonatomic) MVMCoreUICheckMarkView *checkMark; +@property (readonly, nonatomic) BOOL isSelected; +@property (nullable, strong, nonatomic) MFSizeObject *sizeObject; + +//?????? +@property (nullable, strong, nonatomic) UIColor *checkedColor; +@property (nullable, strong, nonatomic) UIColor *unCheckedColor; + +// Label to the right of the check box. +@property (nullable, weak, nonatomic) MFLabel *descriptionLabel; + +// Setter for the descriptionLabel.text. Also sets the accessibility text. +@property (nullable, strong, nonatomic) NSString *descriptionText; +@property (nullable, strong, nonatomic) NSAttributedString *descriptionAttributedText; + +// A block that is called when the switch is selected. +@property (nullable, copy, nonatomic) void (^switchSelected)(BOOL selected); + +//convenient method to get a check box ++ (nullable instancetype)mfCheckBox; ++ (nullable instancetype)mfCheckBoxWithCheckedColor:(nullable UIColor *)checkedColor unCheckColor:(nullable UIColor *)unCheckedColor text:(nullable NSString *)text; ++ (nullable instancetype)mfCheckBoxWithCheckedColor:(nullable UIColor *)checkedColor unCheckColor:(nullable UIColor *)unCheckedColor atributedText:(nullable NSAttributedString *)attributedText; +//Check mark with rounded rect (Prepay - corner radius = 5) ++ (nullable instancetype)mfCheckBoxWithRoundedRect; + +// convenient init +- (nullable instancetype)initWithCheckedColor:(nullable UIColor *)checkedColor unCheckColor:(nullable UIColor *)unCheckedColor text:(nullable NSString *)text; +- (nullable instancetype)initWithCheckedColor:(nullable UIColor *)checkedColor unCheckColor:(nullable UIColor *)unCheckedColor attributedText:(nullable NSAttributedString *)attributedText; +- (nullable instancetype)initWithCheckMarkView:(nullable MVMCoreUICheckMarkView *)checkMarkView checkedColor:(nullable UIColor *)checkedColor unCheckColor:(nullable UIColor *)unCheckedColor text:(nullable NSString *)text; +- (nullable instancetype)initWithCheckMarkView:(nullable MVMCoreUICheckMarkView *)checkMarkView checkedColor:(nullable UIColor *)checkedColor unCheckColor:(nullable UIColor *)unCheckedColor attributedText:(nullable NSAttributedString *)attributedText; + +//configures +- (void)setSelected:(BOOL)selected; +- (void)setSelected:(BOOL)selected animated:(BOOL)animated; +- (void)setColor:(nullable UIColor *)color forState:(UIControlState)state; +- (void)setCheckBoxBorder:(nullable UIColor *)color; + +// helper +- (void)enable:(BOOL)enable; + +//accessibility +- (void)setValueForAccessibilityText:(nullable NSString *)text; +- (void)hideDescriptionLabelAndPinCheckboxToRight; + +@end diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m new file mode 100644 index 00000000..ad6bf187 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -0,0 +1,378 @@ +// +// MVMCoreUICheckBox.m +// myverizon +// +// Created by Suresh, Kamlesh on 11/25/15. +// Update For new Design by Chris Yang on 2/20/26 +// Copyright © 2015 Verizon Wireless. All rights reserved. +// + +#import "MVMCoreUICheckBox.h" +@import MVMCore.MVMCoreDispatchUtility; +@import MVMCore.MVMCoreGetterUtility; +#import "MFSizeObject.h" +#import "MVMCoreUICommonViewsUtility.h" +#import "NSLayoutConstraint+MFConvenience.h" +#import "UIColor+MFConvenience.h" +#import "MVMCoreUIUtility.h" +#import "MFStyler.h" + +static const CGFloat FaultTolerance = 20.f; +static const CGFloat CheckBoxHeightWidth = 18.0; +@interface MVMCoreUICheckBox () + +@property (nonatomic, readwrite) BOOL isSelected; +@property (weak, nonatomic) UIView *checkedSquare; +@property (weak, nonatomic) UIView *containerView; +@property (nullable, nonatomic, strong) UIColor *checkedBoxBorderColor; +@property (nullable, nonatomic, strong) UIColor *checkMarkLineColor; + +//accessibility +@property (nullable, strong, nonatomic) NSString *accessibilityText; +//Rounded rect check mark +@property (assign, nonatomic)BOOL isRoundRectCheckMark; + +@property (nullable, strong, nonatomic) NSLayoutConstraint *checkboxRightPinConstraint; +@property (nullable, strong, nonatomic) NSLayoutConstraint *descriptionLabelLeadingConstraint; + +@property (nullable, strong, nonatomic) NSLayoutConstraint *checkboxWidth; +@property (nullable, strong, nonatomic) NSLayoutConstraint *checkboxHeight; + +@end + +@implementation MVMCoreUICheckBox + +#pragma mark - convenient class methods + ++ (instancetype)mfCheckBox { + MVMCoreUICheckBox *checkBox = [[self alloc] initWithFrame:CGRectZero]; + checkBox.translatesAutoresizingMaskIntoConstraints = NO; + return checkBox ; +} + ++ (nullable instancetype)mfCheckBoxWithRoundedRect{ + MVMCoreUICheckBox *checkBox = [[self alloc] initWithRoundRect:true]; + checkBox.translatesAutoresizingMaskIntoConstraints = NO; + return checkBox ; +} + ++ (instancetype)mfCheckBoxWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text { + MVMCoreUICheckBox *checkBox = [[self alloc] initWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:text]; + checkBox.translatesAutoresizingMaskIntoConstraints = NO; + return checkBox; +} + ++ (instancetype)mfCheckBoxWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor atributedText:(NSAttributedString *)attributedText { + MVMCoreUICheckBox *checkBox = [[self alloc] initWithCheckedColor:checkedColor unCheckColor:unCheckedColor attributedText:attributedText]; + checkBox.translatesAutoresizingMaskIntoConstraints = NO; + return checkBox; +} + +#pragma mark - inits + +- (instancetype)initWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text { + if (self = [super init]) { + [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:text]; + [self addAccessibleProperties]; + } + return self; +} + +- (instancetype)initWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor attributedText:(NSAttributedString *)attributedText { + if (self = [super init]) { + [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:nil]; + self.descriptionAttributedText = attributedText; + [self addAccessibleProperties]; + } + return self; +} + +- (nullable instancetype)initWithCheckMarkView:(nullable MVMCoreUICheckMarkView *)checkMarkView checkedColor:(nullable UIColor *)checkedColor unCheckColor:(nullable UIColor *)unCheckedColor text:(nullable NSString *)text { + if (self = [super init]) { + self.checkMark = checkMarkView; + [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:text]; + [self addAccessibleProperties]; + } + return self; +} + +- (nullable instancetype)initWithCheckMarkView:(nullable MVMCoreUICheckMarkView *)checkMarkView checkedColor:(nullable UIColor *)checkedColor unCheckColor:(nullable UIColor *)unCheckedColor attributedText:(nullable NSAttributedString *)attributedText { + if (self = [super init]) { + self.checkMark = checkMarkView; + [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:nil]; + self.descriptionAttributedText = attributedText; + [self addAccessibleProperties]; + } + return self; +} + +- (instancetype)initWithRoundRect:(BOOL)isRoundRect { + self = [super init]; + if (self) { + self.isRoundRectCheckMark = isRoundRect; + [self setupWithCheckedColor:[UIColor whiteColor] unCheckColor:[UIColor whiteColor] text:nil]; + [self addAccessibleProperties]; + [self setCheckMarkLayer]; + } + return self; +} + +//default inits +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self setupWithCheckedColor:[UIColor whiteColor] unCheckColor:[UIColor whiteColor] text:nil]; + [self addAccessibleProperties]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setupWithCheckedColor:[UIColor whiteColor] unCheckColor:[UIColor whiteColor] text:nil]; + [self addAccessibleProperties]; + } + return self; +} + +- (void)awakeFromNib { + [super awakeFromNib]; + [self setupWithCheckedColor:[UIColor whiteColor] unCheckColor:[UIColor whiteColor] text:nil]; +} + +#pragma mark - set up + +- (void)setupView { + + UIView *containterView = [MVMCoreUICommonViewsUtility commonView]; + containterView.userInteractionEnabled = NO; + if (!self.sizeObject) { + self.sizeObject = [MFSizeObject sizeObjectWithStandardSize:CheckBoxHeightWidth standardiPadPortraitSize:CheckBoxHeightWidth+6]; + } + + //checked circle + if (!self.checkedSquare) { + UIView *checkedSquare = [MVMCoreUICommonViewsUtility commonView]; + checkedSquare.backgroundColor = [UIColor whiteColor]; + [containterView addSubview:checkedSquare]; + CGFloat size = [self.sizeObject getValueBasedOnApplicationWidth]; + NSDictionary *constraints = [NSLayoutConstraint constraintPinView:checkedSquare heightConstraint:YES heightConstant:size widthConstraint:YES widthConstant:size]; + self.checkboxWidth = constraints[ConstraintWidth]; + self.checkboxHeight = constraints[ConstraintHeight]; + [NSLayoutConstraint constraintPinSubview:checkedSquare pinTop:YES pinBottom:YES pinLeft:YES pinRight:NO]; + + self.checkboxRightPinConstraint = [checkedSquare.trailingAnchor constraintEqualToAnchor:containterView.trailingAnchor]; + + [NSLayoutConstraint constraintPinSubview:checkedSquare pinCenterX:NO pinCenterY:YES]; + self.checkedSquare = checkedSquare; + [self setCheckBoxBorder:[UIColor blackColor]]; + } + + //check mark + if (!self.checkMark) { + MVMCoreUICheckMarkView *checkMark = [[MVMCoreUICheckMarkView alloc] initWithFrame:self.frame]; + checkMark.lineWidth = 2.0; + self.checkMark = checkMark; + self.checkMark.translatesAutoresizingMaskIntoConstraints = NO; + [self.checkedSquare addSubview:self.checkMark]; + [self.checkMark.widthAnchor constraintEqualToAnchor:self.checkedSquare.widthAnchor multiplier:.4].active = YES; + [self.checkMark.heightAnchor constraintEqualToAnchor:self.checkedSquare.heightAnchor multiplier:.4].active = YES; + [self.checkMark.centerXAnchor constraintEqualToAnchor:self.checkedSquare.centerXAnchor].active = YES; + [self.checkMark.centerYAnchor constraintEqualToAnchor:self.checkedSquare.centerYAnchor].active = YES; + } else { + [self.checkedSquare addSubview:self.checkMark]; + } + + //label + if (!self.descriptionLabel) { + MFLabel *descriptionLabel = [MFLabel commonLabelB2:YES]; + [containterView addSubview:descriptionLabel]; + [NSLayoutConstraint constraintPinSubview:descriptionLabel pinCenterX:NO pinCenterY:YES]; + [NSLayoutConstraint constraintPinSubview:descriptionLabel pinTop:NO pinBottom:NO pinLeft:NO pinRight:YES]; + + self.descriptionLabelLeadingConstraint = [NSLayoutConstraint constraintWithItem:descriptionLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.checkedSquare attribute:NSLayoutAttributeTrailing multiplier:1 constant:11]; + self.descriptionLabelLeadingConstraint.active = YES; + + self.descriptionLabelLeadingConstraint.active = YES; + self.descriptionLabel = descriptionLabel; + [self setSelected:NO]; + } + + if (!self.containerView) { + [self addSubview:containterView]; + self.containerView = containterView; + [NSLayoutConstraint constraintPinSubviewToSuperview:containterView]; + } +} + +- (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text { + [self setupView]; + if (checkedColor) { + self.checkedColor = checkedColor; + } + if (unCheckedColor) { + self.unCheckedColor = unCheckedColor; + } + [self setDescriptionText:text]; +} + +- (void)updateView:(CGFloat)size { + [MVMCoreDispatchUtility performBlockOnMainThread:^{ + [self.descriptionLabel updateView:size]; + if ([self.checkMark respondsToSelector:@selector(updateView:)]) { + CGFloat width = [self.sizeObject getValueBasedOnSize:size]; + self.checkboxWidth.constant = width; + self.checkboxHeight.constant = width; + [self.checkMark updateView:size]; + } + }]; +} + +- (void)setCheckMarkLayer { + self.checkedSquare.layer.cornerRadius = self.isRoundRectCheckMark ? 5.0f : 0; +} + +#pragma mark - XIB Helpers + +- (instancetype)awakeAfterUsingCoder:(NSCoder *)aDecoder { + if ([self subviews].count == 0) { + return [MVMCoreUICheckBox mfCheckBox]; + } else { + return self; + } +} + +#pragma mark - control methods + +- (void)setSelected:(BOOL)selected { + [self setSelected:selected animated:YES]; +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [self addAccessibilityLabel:selected]; + + self.isSelected = selected; + if (self.switchSelected) { + self.switchSelected(selected); + } + if (selected) { + [UIView animateWithDuration:0.2 delay:0.1 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.checkedSquare.backgroundColor = self.checkedColor; + } completion:nil]; + [self.checkMark updateCheckSelected:YES animated:animated]; + } else { + [UIView animateWithDuration:0.2 delay:0.1 options:UIViewAnimationOptionCurveEaseOut animations:^{ + self.checkedSquare.backgroundColor = self.unCheckedColor; + } completion:nil]; + [self.checkMark updateCheckSelected:NO animated:animated]; + } +} + +- (void)setColor:(nullable UIColor *)color forState:(UIControlState)state { + if (color) { + switch (state) { + case UIControlStateNormal: + self.unCheckedColor = color; + break; + case UIControlStateSelected: + self.checkedColor = color; + break; + default: + break; + } + } +} + +#pragma mark - ui control subclass + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + if ([self touchIsOutside:[touches anyObject]]) { + [self sendActionsForControlEvents:UIControlEventTouchUpOutside]; + } else { + [self setSelected:!self.isSelected]; + [self sendActionsForControlEvents:UIControlEventTouchUpInside]; + } +} + +- (BOOL)touchIsOutside:(UITouch *)touch { + CGPoint endLocation = [touch locationInView:self]; + CGFloat x = endLocation.x; + CGFloat y = endLocation.y; + CGFloat widthLimit = self.frame.size.width + FaultTolerance; + CGFloat heightLimt = self.frame.size.height + FaultTolerance; + if (x < -FaultTolerance || y < -FaultTolerance || x > widthLimit || y > heightLimt) { + return YES; + } else { + return NO; + } +} + +#pragma mark - setter + +- (void)setDescriptionAttributedText:(NSAttributedString *)descriptionAttributedText { + self.descriptionLabel.text = nil; + self.descriptionLabel.attributedText = descriptionAttributedText; + [self setValueForAccessibilityText:[descriptionAttributedText string]]; +} + +- (void)setDescriptionText:(NSString *)descriptionText { + self.descriptionLabel.attributedText = nil; + self.descriptionLabel.text = descriptionText; + [self setValueForAccessibilityText:descriptionText]; +} + +#pragma mark - helper + +- (void)enable:(BOOL)enable { + self.userInteractionEnabled = enable; + //BR design change + if (!self.checkMarkLineColor) { + self.checkMarkLineColor = self.checkMark.lineColor; + } + + if (enable) { + self.checkedSquare.layer.borderColor = self.checkedBoxBorderColor.CGColor; + self.checkMark.lineColor = self.checkMarkLineColor; + self.descriptionLabel.alpha = 1.0; + } else { + self.checkedSquare.layer.borderColor = [UIColor mfSilver].CGColor; + self.checkMark.lineColor = [UIColor mfSilver]; + self.descriptionLabel.alpha = DisableOppacity; + } +} + +- (void)setCheckBoxBorder:(UIColor *)color { + self.checkedSquare.layer.borderWidth = 1; + self.checkedSquare.layer.borderColor = color.CGColor; + //BR design + self.checkedBoxBorderColor = color; +} + +#pragma mark - Accessibility +- (BOOL)isAccessibilityElement { + return YES; +} + +- (void)setValueForAccessibilityText:(nullable NSString *)text { + self.accessibilityText = text; + [self addAccessibilityLabel:self.isSelected]; +} +- (void)addAccessibleProperties { + self.accessibilityTraits = UIAccessibilityTraitNone; + self.accessibilityHint = [MVMCoreUIUtility hardcodedStringWithKey:@"checkbox_action_hint"]; +} + +- (void)addAccessibilityLabel:(BOOL)selected { + NSString *state = selected?[MVMCoreUIUtility hardcodedStringWithKey:@"checkbox_checked_state"]:[MVMCoreUIUtility hardcodedStringWithKey:@"checkbox_unchecked_state"]; + NSString *description = self.accessibilityText.length ? self.accessibilityText:@""; + self.accessibilityLabel = [NSString stringWithFormat:[MVMCoreUIUtility hardcodedStringWithKey:@"checkbox_desc_state"],description,state]; +} + +- (void)hideDescriptionLabelAndPinCheckboxToRight { + self.descriptionLabel.hidden = YES; + self.checkboxRightPinConstraint.active = YES; + self.descriptionLabelLeadingConstraint.constant = 0; +} + +@end diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.h b/MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.h new file mode 100644 index 00000000..694fc72b --- /dev/null +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.h @@ -0,0 +1,17 @@ +// +// MVMCoreUICheckMarkView.h +// mobilefirst +// +// Created by Shreyas Seshamani on 2/17/16. +// Copyright © 2016 Verizon Wireless. All rights reserved. +// + +#import +#import + +@interface MVMCoreUICheckMarkView : MFView + +@property (nonatomic) CGFloat lineWidth; +@property (nonatomic, strong) UIColor *lineColor; +- (void)updateCheckSelected:(BOOL)selected animated:(BOOL)animated; +@end diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.m new file mode 100644 index 00000000..6889870b --- /dev/null +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.m @@ -0,0 +1,133 @@ +// +// MVMCoreUICheckMarkView.m +// mobilefirst +// +// Created by Shreyas Seshamani on 2/17/16. +// Copyright © 2016 Verizon Wireless. All rights reserved. +// + +#import "MVMCoreUICheckMarkView.h" +#import +#import + +@interface MVMCoreUICheckMarkView () + +@property (nonatomic) float drawPercentage; +@property (strong, nonatomic) NSTimer * animationTimer; +@property (strong, nonatomic) CAShapeLayer *checkLayer; +@property (nonatomic) BOOL selected; +@end + +@implementation MVMCoreUICheckMarkView + +//Offsets based on the 124x124 example checkmark +const float startXOffset = (42.0/124.0); +const float startYOffset = (66.0/124.0); +const float pivotXOffset = (58.0/124.0); +const float pivotYOffset = (80.0/124.0); +const float endXOffset = (83.0/124.0); +const float endYOffset = (46.0/124.0); +const float pivotPercentage = 0.34; +const float endPercentage = 1.0 - pivotPercentage; +const float animationInterval = 0.01; + +- (void)setupView { + [super setupView]; + self.backgroundColor = [UIColor clearColor]; + self.drawPercentage = 1.0; + _lineColor = [UIColor blackColor]; + _lineWidth = 1.0; +} + +- (void)updateView:(CGFloat)size { + [super updateView:size]; +} + +- (void)drawCheck { + if (!self.checkLayer) { + [self layoutIfNeeded]; + UIBezierPath *path = [UIBezierPath bezierPath]; + [path moveToPoint:CGPointMake(self.lineWidth/2, self.bounds.size.height*.55)]; + [path addLineToPoint:CGPointMake(self.bounds.size.width*.45, self.bounds.size.height*.85)]; + [path addLineToPoint:CGPointMake(self.bounds.size.width - self.lineWidth/2, self.lineWidth/2)]; + + self.checkLayer = [[CAShapeLayer alloc] init]; + self.checkLayer.frame = self.bounds; + [self.layer addSublayer:self.checkLayer]; + self.checkLayer.strokeColor = self.lineColor.CGColor ?: [UIColor blackColor].CGColor; + self.checkLayer.fillColor = [UIColor clearColor].CGColor; + self.checkLayer.path = path.CGPath; + self.checkLayer.lineWidth = self.lineWidth; + + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + self.checkLayer.strokeEnd = 0.0; + [CATransaction commit]; + } +} + +- (void)updateCheckSelected:(BOOL)selected animated:(BOOL)animated { + [MVMCoreDispatchUtility performBlockOnMainThread:^{ + self.selected = selected; + + // animate this bar + [self drawCheck]; + + CAShapeLayer *layer; + if (self.checkLayer.presentationLayer && animated) { + layer = self.checkLayer.presentationLayer; + } else { + layer = self.checkLayer; + } + + if (animated) { + CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + animateStrokeEnd.fillMode = kCAFillModeBoth; + animateStrokeEnd.removedOnCompletion = NO; + animateStrokeEnd.duration = .3; + + animateStrokeEnd.fromValue = [NSNumber numberWithFloat:[layer strokeEnd]]; + if (selected) { + animateStrokeEnd.toValue = [NSNumber numberWithFloat:1]; + } else { + animateStrokeEnd.toValue = [NSNumber numberWithFloat:0]; + } + + animateStrokeEnd.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; + [layer addAnimation:animateStrokeEnd forKey:@"strokeEndAnimation"]; + } else { + [layer removeAllAnimations]; + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + if (selected) { + layer.strokeEnd = 1.0; + } else { + layer.strokeEnd = 0.0; + } + [CATransaction commit]; + } + }]; +} + +- (void)setLineWidth:(CGFloat)lineWidth { + _lineWidth = lineWidth; + if (self.checkLayer) { + [self.checkLayer removeFromSuperlayer]; + self.checkLayer = nil; + [self updateCheckSelected:self.selected animated:NO]; + } +} + +- (void)setLineColor:(UIColor *)lineColor { + _lineColor = lineColor; + if (self.checkLayer) { + self.checkLayer.strokeColor = lineColor.CGColor; + [self updateCheckSelected:self.selected animated:NO]; + } +} + +- (void)layoutSubviews { + [self drawCheck]; +} + +@end diff --git a/MVMCoreUI/MVMCoreUI.h b/MVMCoreUI/MVMCoreUI.h index ccf05ccb..258d5d30 100644 --- a/MVMCoreUI/MVMCoreUI.h +++ b/MVMCoreUI/MVMCoreUI.h @@ -81,6 +81,8 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; #import #import #import +#import +#import #pragma mark Buttons #import diff --git a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings index 477a47d0..9c830eef 100644 --- a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings @@ -29,3 +29,8 @@ // Camera "AccCameraButton" = "Camera Button"; "AccCameraHint" = "Double tap to launch camera for scanning"; +// Checkbox +"checkbox_action_hint" = "Double tap to change state"; +"checkbox_checked_state" = "Checked"; +"checkbox_unchecked_state" = "Unchecked"; +"checkbox_desc_state" = "%@ CheckBox %@"; diff --git a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings index caeb41c4..255b6e16 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings @@ -7,11 +7,14 @@ */ "AccCloseButton" = "Cerrar"; +// Tab "AccTab" = ", pestaña"; "AccTabHint" = "Toca dos veces para seleccionar."; +// top alert "toptabbar_tab_selected" = ", pestaña, Seleccionado"; "AccTopAlertClosed" = "La notificación de alerta máxima está desactivada."; "top_alert_notification" = "Notificación de alerta máxima"; +// Textfield "textfield_today_string" = "Hoy"; "textfield_error_message" = "%@.\n El mensaje de error.\n %@"; "textfield_picker_item" = " artículo de selector"; @@ -25,3 +28,8 @@ // Camera "AccCameraButton" = "Botón de cámara"; "AccCameraHint" = "Toca dos veces para iniciar la cámara para escanear"; +// Checkbox +"checkbox_action_hint" = "Toca dos veces para cambiar el estado"; +"checkbox_checked_state" = "Verificado"; +"checkbox_unchecked_state" = "Sin marcar"; +"checkbox_desc_state" = "%@ Casilla %@"; diff --git a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings index caeb41c4..255b6e16 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings @@ -7,11 +7,14 @@ */ "AccCloseButton" = "Cerrar"; +// Tab "AccTab" = ", pestaña"; "AccTabHint" = "Toca dos veces para seleccionar."; +// top alert "toptabbar_tab_selected" = ", pestaña, Seleccionado"; "AccTopAlertClosed" = "La notificación de alerta máxima está desactivada."; "top_alert_notification" = "Notificación de alerta máxima"; +// Textfield "textfield_today_string" = "Hoy"; "textfield_error_message" = "%@.\n El mensaje de error.\n %@"; "textfield_picker_item" = " artículo de selector"; @@ -25,3 +28,8 @@ // Camera "AccCameraButton" = "Botón de cámara"; "AccCameraHint" = "Toca dos veces para iniciar la cámara para escanear"; +// Checkbox +"checkbox_action_hint" = "Toca dos veces para cambiar el estado"; +"checkbox_checked_state" = "Verificado"; +"checkbox_unchecked_state" = "Sin marcar"; +"checkbox_desc_state" = "%@ Casilla %@";