diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index 5f60081e..1030fb8c 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -37,7 +37,7 @@ import Foundation private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor - case title + case title = "label" case isEnabled case feedback case errorMessage = "errorMsg" diff --git a/MVMCoreUI/Categories/NSLayoutConstraintExtension.swift b/MVMCoreUI/Categories/NSLayoutConstraintExtension.swift index bf6c8f65..4057a88c 100644 --- a/MVMCoreUI/Categories/NSLayoutConstraintExtension.swift +++ b/MVMCoreUI/Categories/NSLayoutConstraintExtension.swift @@ -9,36 +9,52 @@ import Foundation public extension NSLayoutConstraint { - static func pinSubviewsCenter(leftView: UIView, rightView: UIView) { - guard let superView = leftView.superview else { - return + + /// Pins the views vertically in the super view, allowing the super to expand depending on the tallest view. Shorter views are aligned center. + static func pinViewsVerticalExpandableAlignCenter(_ views: [UIView]) { + for view in views { + guard let superView = view.superview else { + return + } + view.centerYAnchor.constraint(equalTo: superView.centerYAnchor).isActive = true + view.topAnchor.constraint(greaterThanOrEqualTo: superView.layoutMarginsGuide.topAnchor).isActive = true + superView.layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor).isActive = true + + var constraint = view.topAnchor.constraint(equalTo: superView.layoutMarginsGuide.topAnchor) + constraint.priority = .defaultLow + constraint.isActive = true + + constraint = superView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor) + constraint.priority = .defaultLow + constraint.isActive = true } - leftView.centerYAnchor.constraint(equalTo: superView.centerYAnchor).isActive = true - leftView.leftAnchor.constraint(equalTo: superView.layoutMarginsGuide.leftAnchor).isActive = true - leftView.topAnchor.constraint(greaterThanOrEqualTo: superView.layoutMarginsGuide.topAnchor).isActive = true - superView.layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: leftView.bottomAnchor).isActive = true + } + + /// Pins the views vertically in the super view, allowing the super to expand depending on the tallest view. Shorter views are aligned top. + static func pinViewsVerticalExpandableAlignTop(_ views: [UIView]) { + for view in views { + guard let superView = view.superview else { + return + } + view.topAnchor.constraint(equalTo: superView.layoutMarginsGuide.topAnchor).isActive = true + superView.layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor).isActive = true - var constraint = leftView.topAnchor.constraint(equalTo: superView.layoutMarginsGuide.topAnchor) - constraint.priority = .defaultLow - constraint.isActive = true - - constraint = superView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: leftView.bottomAnchor) - constraint.priority = .defaultLow - constraint.isActive = true - - rightView.leftAnchor.constraint(greaterThanOrEqualTo: leftView.rightAnchor, constant: 16).isActive = true - - rightView.centerYAnchor.constraint(equalTo: superView.centerYAnchor).isActive = true - superView.layoutMarginsGuide.rightAnchor.constraint(equalTo: rightView.rightAnchor).isActive = true - rightView.topAnchor.constraint(greaterThanOrEqualTo: superView.layoutMarginsGuide.topAnchor).isActive = true - superView.layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor).isActive = true - - constraint = rightView.topAnchor.constraint(equalTo: superView.layoutMarginsGuide.topAnchor) - constraint.priority = .defaultLow - constraint.isActive = true - - constraint = superView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: rightView.bottomAnchor) - constraint.priority = .defaultLow - constraint.isActive = true + let constraint = superView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor) + constraint.priority = .defaultLow + constraint.isActive = true + } + } + + /// Pins a view to the left and a view to the right, flexible space in between. The super can expand depending on the taller view. Shorter views are aligned top if alignTop true, else aligned center. + static func pinViews(leftView: UIView, rightView: UIView, alignTop: Bool) { + guard let superView = leftView.superview else { return } + if alignTop { + pinViewsVerticalExpandableAlignTop([leftView, rightView]) + } else { + pinViewsVerticalExpandableAlignCenter([leftView, rightView]) + } + leftView.leadingAnchor.constraint(equalTo: superView.layoutMarginsGuide.leadingAnchor).isActive = true + superView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightView.trailingAnchor).isActive = true + rightView.leftAnchor.constraint(greaterThanOrEqualTo: leftView.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true } } diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift index 089352c7..840f4763 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift @@ -10,13 +10,14 @@ import UIKit @objcMembers open class ImageHeadlineBody: View { let headlineBody = HeadlineBody(frame: .zero) - let imageView = MFLoadImageView() + let imageView = MFLoadImageView(pinnedEdges: .all) var constraintBetweenImageLabelsConstant: CGFloat = 16 var constraintBetweenImageLabels: NSLayoutConstraint? // MARK: - MFViewProtocol open override func setupView() { + super.setupView() guard subviews.count == 0 else { return } @@ -26,23 +27,9 @@ import UIKit addSubview(headlineBody) addSubview(imageView) - headlineBody.topAnchor.constraint(equalTo: topAnchor).isActive = true + NSLayoutConstraint.pinViewsVerticalExpandableAlignCenter([imageView, headlineBody]) rightAnchor.constraint(equalTo: headlineBody.rightAnchor).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: headlineBody.bottomAnchor).isActive = true - var constraint = bottomAnchor.constraint(equalTo: headlineBody.bottomAnchor) - constraint.priority = .defaultLow - constraint.isActive = true - - imageView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true imageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true - imageView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: imageView.bottomAnchor).isActive = true - constraint = bottomAnchor.constraint(equalTo: imageView.bottomAnchor) - constraint.priority = UILayoutPriority(rawValue: 200) - constraint.isActive = true - constraint = imageView.topAnchor.constraint(equalTo: topAnchor) - constraint.priority = UILayoutPriority(rawValue: 200) - constraint.isActive = true constraintBetweenImageLabels = headlineBody.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: constraintBetweenImageLabelsConstant) constraintBetweenImageLabels?.isActive = true diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggle.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggle.swift index 7359ed3c..07639dbe 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggle.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggle.swift @@ -27,7 +27,7 @@ import UIKit headlineBodyLink.headlineBody.styleListItem() addSubview(headlineBodyLink) addSubview(toggle) - NSLayoutConstraint.pinSubviewsCenter(leftView: headlineBodyLink, rightView: toggle) + NSLayoutConstraint.pinViews(leftView: headlineBodyLink, rightView: toggle, alignTop: false) } // MARK: - MVMCoreUIMoleculeViewProtoco diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggle.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggle.swift index 324d63da..8df94fa8 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggle.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggle.swift @@ -31,7 +31,7 @@ import UIKit view.addSubview(headlineBody) view.addSubview(toggle) - NSLayoutConstraint.pinSubviewsCenter(leftView: headlineBody, rightView: toggle) + NSLayoutConstraint.pinViews(leftView: headlineBody, rightView: toggle, alignTop: false) } // MARK:- ModelMoleculeViewProtocol diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift index 3d00b820..f2925cc9 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggle.swift @@ -28,7 +28,7 @@ import UIKit addSubview(label) addSubview(toggle) label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) - NSLayoutConstraint.pinSubviewsCenter(leftView: label, rightView: toggle) + NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false) } // MARK:- ModelMoleculeViewProtocol diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.h b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.h index d1b2d470..4503872c 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.h +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.h @@ -30,16 +30,16 @@ - (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; // Used primarily for when button presses will expand or collapse. (Short view button will need to be set manually) -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; +- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; +- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; // Used when button uses standard action map. -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; +- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; // Convenience change functions - (void)setTopMessage:(nullable NSString *)topMessage; -- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; -- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; +- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; +- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; // Setters for making buttons expand and collapse the cell. - (void)setButtonPressToExpand; diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m index 55bb6bfd..f215fa0b 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m @@ -41,10 +41,10 @@ - (void)setupTopAlertWithButton:(MVMCoreUITopAlertMainView *)topAlertWithButton; // Sets up the whole view without setting button action. -- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle; +- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle; // Sets up the whole view while setting button action. -- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; +- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; @end @@ -97,14 +97,8 @@ [self setupTopAlertWithButton:topAlertWithButton]; // Sets the color - if (topAlertObject.backgroundColor) { - self.backgroundColor = topAlertObject.backgroundColor; - } else { - self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; - } - if (topAlertObject.textColor) { - self.shortView.label.textColor = topAlertObject.textColor; - } + self.shortView.label.textColor = topAlertObject.textColor ?: [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type]; + self.backgroundColor = topAlertObject.backgroundColor ?: [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; if (topAlertWithButton.label.text.length > 0) { [self expand:NO]; @@ -112,8 +106,10 @@ } else { // Old style, has no top alert and main view is limited. - self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; [self setupTopMessage:nil]; - MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:self.backgroundColor message:topAlertObject.message subMessage:nil closeButton:YES animationDelegate:animationDelegate]; + self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; + UIColor *contentColor = [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type]; + [self setupTopMessage:nil]; + MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:self.backgroundColor contentColor:contentColor message:topAlertObject.message subMessage:nil closeButton:YES animationDelegate:animationDelegate]; [self setupTopAlertWithButton:topAlertWithButton]; [self expand:NO]; } @@ -121,29 +117,29 @@ return self; } -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { +- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { if ([self init]) { self.animationDelegate = animationDelegate; self.viewToLayout = viewTolayout; - [self setupViewWithTopMessage:topMessage message:message subMessage:nil buttonTitle:buttonTitle]; + [self setupViewWithTopMessage:topMessage message:message subMessage:nil contentColor:contentColor buttonTitle:buttonTitle]; } return self; } -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { +- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { if ([self init]) { self.animationDelegate = animationDelegate; self.viewToLayout = viewTolayout; - [self setupViewWithTopMessage:topMessage message:message subMessage:subMessage buttonTitle:buttonTitle]; + [self setupViewWithTopMessage:topMessage message:message subMessage:subMessage contentColor:contentColor buttonTitle:buttonTitle]; } return self; } -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { +- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { if ([self init]) { self.animationDelegate = animationDelegate; self.viewToLayout = viewTolayout; - [self setupViewWithTopMessage:topMessage message:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; + [self setupViewWithTopMessage:topMessage message:message subMessage:subMessage contentColor:contentColor actionMap:actionMap additionalData:additionalData]; } return self; } @@ -174,19 +170,19 @@ [NSLayoutConstraint constraintPinSubview:topAlertWithButton pinTop:NO topConstant:0 pinBottom:YES bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0]; } -- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle { +- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle { [self setupTopMessage:topMessage]; - MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] message:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:nil]; + MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] contentColor:contentColor message:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:nil]; [self setupTopAlertWithButton:topAlertWithButton]; } -- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { +- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { [self setupTopMessage:topMessage]; - MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] message:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; + MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] contentColor:contentColor message:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; [self setupTopAlertWithButton:topAlertWithButton]; } @@ -204,17 +200,17 @@ }]; } -- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { +- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { [MVMCoreDispatchUtility performBlockOnMainThread:^{ [self setTopMessage:topMessage]; - [self.buttonView setupWithMessage:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; + [self.buttonView setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData]; }]; } -- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { +- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { [MVMCoreDispatchUtility performBlockOnMainThread:^{ [self setTopMessage:topMessage]; - [self.buttonView setupWithMessage:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:userActionHandler]; + [self.buttonView setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:buttonTitle userActionHandler:userActionHandler]; }]; } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.h b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.h index 50dd9b26..4842fc32 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.h +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.h @@ -22,16 +22,16 @@ // Standard - (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id )animationDelegate; -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; // inits with images -- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; -- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; // Setters for label and button. -- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; -- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; +- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; +- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; // Setters for button. - (void)setupButtonWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; @@ -40,13 +40,13 @@ #pragma mark - legacy inits // Legacy init: inits with a label and button, no close button or icon. -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; // Legacy init: inits with a label and possible icon and close button. No main button. -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; // Legacy init: inits with a label and button, no close button or icon. If passing in a block to use for the button, the top alert delegate button functions will not be called. -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; @end diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m index e51ffc83..5b87d163 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m @@ -60,52 +60,49 @@ - (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id )animationDelegate { if ([self init]) { - if (topAlertObject.backgroundColor) { - self.backgroundColor = topAlertObject.backgroundColor; - } else { - self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; - } + UIColor *contentColor = topAlertObject.textColor ?: [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type]; + self.backgroundColor = topAlertObject.backgroundColor ?: [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; [self setupViewWithLabelAndImage:topAlertObject.imageNameOrURL topImage:topAlertObject.aboveTextImageString]; [self setupCloseButton:topAlertObject.useCloseButton animationDelegate:animationDelegate]; - [self setupWithMessage:topAlertObject.title subMessage:topAlertObject.message color:topAlertObject.textColor actionMap:topAlertObject.buttonMap additionalData:topAlertObject.additionalData]; + [self setupWithMessage:topAlertObject.title subMessage:topAlertObject.message color:contentColor actionMap:topAlertObject.buttonMap additionalData:topAlertObject.additionalData]; } return self; } -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { // Handles all scenarios. if ([self init]) { self.backgroundColor = color; [self setupViewWithLabelAndImage:nil topImage:nil]; [self setupCloseButton:closeButton animationDelegate:animationDelegate]; - [self setupWithMessage:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; + [self setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData]; } return self; } #pragma mark - inits with images -- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { // Handles all scenarios. if ([self init]) { self.backgroundColor = color; [self setupViewWithLabelAndImage:imageURL topImage:nil]; [self setupCloseButton:closeButton animationDelegate:animationDelegate]; - [self setupWithMessage:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; + [self setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData]; } return self; } -- (nullable instancetype)initWithColor:(nonnull UIColor *)color imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { // No main button. if ([self init]) { self.backgroundColor = color; [self setupViewWithLabelAndImage:imageURL topImage:nil]; [self setupCloseButton:closeButton animationDelegate:animationDelegate]; - [self setupWithMessage:message subMessage:subMessage buttonTitle:nil userActionHandler:NULL]; + [self setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:nil userActionHandler:NULL]; } return self; } @@ -173,7 +170,7 @@ if (closeButton && !self.closeButton) { self.closeButton = [self addCloseButtonWithAnimationDelegate:animationDelegate]; - [self.closeButton setTintColor:self.contentColor ?:[UIColor whiteColor]]; + [self.closeButton setTintColor:self.contentColor ?: [UIColor whiteColor]]; } else if (!closeButton && self.closeButton) { [self.closeButton removeFromSuperview]; self.closeButton = nil; @@ -241,17 +238,19 @@ }]; } -- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - [self setupWithMessage:message subMessage:subMessage color:nil actionMap:actionMap additionalData:additionalData]; -} - -- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { +- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { self.message = message; self.subMessage = subMessage; + self.contentColor = color; [MVMCoreDispatchUtility performBlockOnMainThread:^{ // Sets the string - self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:nil]; + self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:color]; + + // Sets the color + if (color) { + [self.closeButton setTintColor:color]; + } // Sets the button [self setupButtonWithButtonTitle:buttonTitle userActionHandler:userActionHandler]; @@ -284,36 +283,36 @@ #pragma mark - legacy inits -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { // No icon or close button. if ([self init]) { self.backgroundColor = color; [self setupViewWithLabelAndImage:nil topImage:nil]; - [self setupWithMessage:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; + [self setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData]; } return self; } -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { // No main button. if ([self init]) { self.backgroundColor = color; [self setupViewWithLabelAndImage:nil topImage:nil]; + [self setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:nil userActionHandler:NULL]; [self setupCloseButton:closeButton animationDelegate:animationDelegate]; - [self setupWithMessage:message subMessage:subMessage buttonTitle:nil userActionHandler:NULL]; } return self; } -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { +- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { // No icon or close button. Custom button action. if ([self init]) { self.backgroundColor = color; [self setupViewWithLabelAndImage:nil topImage:nil]; - [self setupWithMessage:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:userActionHandler]; + [self setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:buttonTitle userActionHandler:userActionHandler]; } return self; } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h index 9850cca3..ca9520f3 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h @@ -47,9 +47,12 @@ // Can be subclassed for custom views. - (nonnull MVMCoreUITopAlertBaseView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor; -// Get the background color based on the type +/// Get the background color based on the type - (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type; +/// Get the content color based on the type +- (nonnull UIColor *)getContentColorForType:(nullable NSString *)type; + // Set the status bar color. Used for updating the status bar when the view changes. - (void)setStatusBarColor:(nullable UIColor *)statusBarColor statusBarStyle:(UIStatusBarStyle)style; diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index b65f7423..947e6ffc 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -114,6 +114,14 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; } } +- (nonnull UIColor *)getContentColorForType:(nullable NSString *)type { + if ([type isEqualToString:ValueTypeError]) { + return [UIColor blackColor]; + } else { + return [UIColor whiteColor]; + } +} + - (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler { self.animationDelegate = animationDelegate; @@ -126,7 +134,8 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; MVMCoreUITopAlertBaseView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor]; if (!statusBarColor) { statusBarColor = [UIColor whiteColor]; - } + } +#warning This logic is incomplete, it is possible to show the wrong status bar color here if the background is yellow or pumpkin. UIStatusBarStyle statusBarStyle = statusBarColor == [UIColor whiteColor] ? UIStatusBarStyleDefault : UIStatusBarStyleLightContent; [self setStatusBarColor:statusBarColor statusBarStyle:statusBarStyle]; [self showAlertView:view topAlertObject:topAlertObject completionHandler:completionHandler];