From f6021bb3825c6d5360dbd33d8934eb3dc66ce4c7 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 2 Jul 2019 10:23:58 -0400 Subject: [PATCH 1/2] header footer as containers --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + MVMCoreUI/Atoms/Views/Label.swift | 4 + MVMCoreUI/Atoms/Views/MFView.m | 4 + MVMCoreUI/Atoms/Views/ViewConstrainingView.h | 13 +- MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 43 +++++-- MVMCoreUI/Molecules/ButtonView.swift | 4 + MVMCoreUI/Molecules/HeadlineBody.swift | 105 ++++++++++++++++ MVMCoreUI/Molecules/ModuleMolecule.swift | 25 ++-- MVMCoreUI/Molecules/StandardFooterView.swift | 101 ++-------------- MVMCoreUI/Molecules/StandardHeaderView.swift | 112 +++--------------- .../MVMCoreUIMoleculeMappingObject.m | 3 +- 11 files changed, 205 insertions(+), 213 deletions(-) create mode 100644 MVMCoreUI/Molecules/HeadlineBody.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 7ea64bcf..04c2b811 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -161,6 +161,7 @@ D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */; }; D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* StandardHeaderView.swift */; }; D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; }; + D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A638FC22CA98280052ED1F /* HeadlineBody.swift */; }; D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; }; D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; }; @@ -333,6 +334,7 @@ D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackCenteredTemplate.swift; sourceTree = ""; }; D2A514662213885800345BFB /* StandardHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardHeaderView.swift; sourceTree = ""; }; D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerViewController.swift; sourceTree = ""; }; + D2A638FC22CA98280052ED1F /* HeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBody.swift; sourceTree = ""; }; D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = ""; }; D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = ""; }; D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = ""; }; @@ -472,6 +474,7 @@ B8200E142280C4CF007245F4 /* ProgressBar.swift */, B8200E182281DC1A007245F4 /* ProgressBarWithLabel.swift */, D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, + D2A638FC22CA98280052ED1F /* HeadlineBody.swift */, ); path = Molecules; sourceTree = ""; @@ -951,6 +954,7 @@ D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */, 016A1071228122180009D605 /* SwitchLineItem.swift in Sources */, D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */, + D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 35f8ab71..3b35764a 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -370,6 +370,10 @@ extension Label { public func alignment() -> UIStackView.Alignment { return .leading } + + public func copyBackgroundColor() -> Bool { + return true + } } // MARK: - Multi-Action Functionality diff --git a/MVMCoreUI/Atoms/Views/MFView.m b/MVMCoreUI/Atoms/Views/MFView.m index a5754b2a..28bcdd81 100644 --- a/MVMCoreUI/Atoms/Views/MFView.m +++ b/MVMCoreUI/Atoms/Views/MFView.m @@ -47,6 +47,10 @@ #pragma mark - MVMCoreUIMoleculeViewProtocol +- (void)reset { + self.backgroundColor = [UIColor clearColor]; +} + - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { self.json = json; diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h index cf2cf2f9..9ec6c193 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h @@ -30,10 +30,14 @@ @property (nullable, strong, nonatomic) IBOutlet NSLayoutConstraint *topPinLow; @property (nullable, strong, nonatomic) IBOutlet NSLayoutConstraint *bottomPinLow; - -// In updateView, will set horizontal padding to default if set to YES. +/// In updateView, will set horizontal padding to default if set to YES. @property (nonatomic) BOOL updateViewHorizontalDefaults; +/// A molecule if we constrain one. +@property (weak, nullable, nonatomic) UIView *molecule; + +/// A flag for if we should add a molecule from json. +@property (nonatomic) BOOL setupMoleculeFromJSON; // Returns an empty view + (nonnull ViewConstrainingView *)emptyView; @@ -44,6 +48,8 @@ // Can be initialized with a molecule to constrain - (nullable instancetype)initWithMolecule:(nonnull UIView *)molecule alignment:(UIStackViewAlignment)alignment; +#pragma mark - Constraining + // Use these to sets the constants, because subclasses may align differently. - (void)setPinConstantsWithInsets:(UIEdgeInsets)insets; - (void)setTopPinConstant:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right; @@ -63,9 +69,6 @@ // Resets all the constraints to default. - (void)resetConstraints; -// For setting up the view. -- (void)setupView; - // Add a view to be constrained in this view. - (void)addConstrainedView:(nonnull UIView *)view; diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index 8b4406fc..093e1ecc 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -9,12 +9,14 @@ #import "ViewConstrainingView.h" @import MVMCore.MVMCoreConstants; @import MVMCore.MVMCoreDispatchUtility; +@import MVMCore.NSDictionary_MFConvenience; #import "NSLayoutConstraint+MFConvenience.h" #import "MFStyler.h" +#import "MVMCoreUIConstants.h" +#import "MVMCoreUIMoleculeMappingObject.h" @interface ViewConstrainingView () @property (weak, nullable, nonatomic) UIView *constrainedView; -@property (weak, nullable, nonatomic) UIView *molecule; @end @implementation ViewConstrainingView @@ -130,10 +132,12 @@ - (void)show { self.topPin.active = YES; + self.topPinLow.active = YES; } - (void)hide { self.topPin.active = NO; + self.topPinLow.active = NO; } - (void)resetConstraints { @@ -277,8 +281,20 @@ - (void)shouldSetHorizontalMargins:(BOOL)shouldSet { self.updateViewHorizontalDefaults = shouldSet; } - + - (void)shouldSetVerticalMargins:(BOOL)shouldSet { + BOOL useStandardSpacing = shouldSet; + if (shouldSet && [self.molecule respondsToSelector:@selector(useStandardConstraints)]) { + useStandardSpacing = [((UIView *)self.molecule) useStandardConstraints]; + } + + if (useStandardSpacing) { + [self setTopPinConstant:PaddingDefaultVerticalSpacing]; + [self setBottomPinConstant:PaddingDefaultVerticalSpacing]; + } else { + [self setTopPinConstant:0]; + [self setBottomPinConstant:0]; + } } #pragma mark - MVMCoreViewProtocol @@ -312,8 +328,8 @@ #pragma mark - MVMCoreUIMoleculeViewProtocol - (void)reset { - if ([self.constrainedView respondsToSelector:@selector(reset)]) { - [self.constrainedView performSelector:@selector(reset)]; + if ([self.molecule respondsToSelector:@selector(reset)]) { + [self.molecule performSelector:@selector(reset)]; } } @@ -323,11 +339,22 @@ - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; - if (self.molecule) { - [self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; + + [self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; + if (self.setupMoleculeFromJSON && !self.molecule) { + NSDictionary *moleculeJSON = [json dict:KeyMolecule]; + if (moleculeJSON) { + UIView *molecule = [[MVMCoreUIMoleculeMappingObject sharedMappingObject] createMoleculeForJSON:moleculeJSON delegateObject:delegateObject constrainIfNeeded:true]; + if (molecule) { + [self insertSubview:molecule atIndex:0]; + [self pinViewToSuperView:molecule]; + } + } } - if (self.constrainedView && (![self.constrainedView respondsToSelector:@selector(copyBackgroundColor)] || [self.constrainedView performSelector:@selector(copyBackgroundColor)])) { - self.backgroundColor = self.constrainedView.backgroundColor; + if (self.molecule) { + if ([self.molecule respondsToSelector:@selector(copyBackgroundColor)] && [self.molecule performSelector:@selector(copyBackgroundColor)]) { + self.backgroundColor = self.molecule.backgroundColor; + } } } diff --git a/MVMCoreUI/Molecules/ButtonView.swift b/MVMCoreUI/Molecules/ButtonView.swift index d9163ae4..0fc0f3c3 100644 --- a/MVMCoreUI/Molecules/ButtonView.swift +++ b/MVMCoreUI/Molecules/ButtonView.swift @@ -68,6 +68,10 @@ import UIKit return 42 } + open override func copyBackgroundColor() -> Bool { + return true + } + // MARK: - Constraining func setupButton() { if let primaryButton = primaryButton, !subviews.contains(primaryButton) { diff --git a/MVMCoreUI/Molecules/HeadlineBody.swift b/MVMCoreUI/Molecules/HeadlineBody.swift new file mode 100644 index 00000000..9eaa602f --- /dev/null +++ b/MVMCoreUI/Molecules/HeadlineBody.swift @@ -0,0 +1,105 @@ +// +// HeadlineBody.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 7/1/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class HeadlineBody: ViewConstrainingView { + let headlineLabel = Label.commonLabelH2(true) + let messageLabel = Label.commonLabelB2(true) + var spaceBetweenLabels: NSLayoutConstraint? + var leftConstraintTitle: NSLayoutConstraint? + var rightConstraintTitle: NSLayoutConstraint? + var leftConstraintMessage: NSLayoutConstraint? + var rightConstraintMessage: NSLayoutConstraint? + + // MARK: - MVMCoreViewProtocol + open override func updateView(_ size: CGFloat) { + super.updateView(size) + headlineLabel.updateView(size) + messageLabel.updateView(size) + setSpacing() + } + + open override func setupView() { + super.setupView() + guard subviews.count == 0 else { + return + } + translatesAutoresizingMaskIntoConstraints = false + backgroundColor = .clear + clipsToBounds = true + + addSubview(headlineLabel) + addSubview(messageLabel) + + headlineLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + messageLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + + topPin = headlineLabel.topAnchor.constraint(equalTo: topAnchor, constant: 0) + topPin?.isActive = true + + spaceBetweenLabels = messageLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: PaddingTwo) + spaceBetweenLabels?.isActive = true + + leftConstraintTitle = headlineLabel.leftAnchor.constraint(equalTo: leftAnchor) + leftConstraintTitle?.isActive = true + + rightConstraintTitle = rightAnchor.constraint(equalTo: headlineLabel.rightAnchor) + rightConstraintTitle?.isActive = true + + leftConstraintMessage = messageLabel.leftAnchor.constraint(equalTo: leftAnchor) + leftConstraintMessage?.isActive = true + + rightConstraintMessage = rightAnchor.constraint(equalTo: messageLabel.rightAnchor) + rightConstraintMessage?.isActive = true + + bottomPin = bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 0) + bottomPin?.isActive = true + } + + // MARK: - Constraining + public func setSpacing() { + if headlineLabel.hasText && messageLabel.hasText { + spaceBetweenLabels?.constant = PaddingTwo + } else { + spaceBetweenLabels?.constant = 0 + } + } + + open override func setLeftPinConstant(_ constant: CGFloat) { + leftConstraintTitle?.constant = constant + leftConstraintMessage?.constant = constant + } + + open override func setRightPinConstant(_ constant: CGFloat) { + rightConstraintTitle?.constant = constant + rightConstraintMessage?.constant = constant + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + let headlineJSON = json?.optionalDictionaryForKey("headline") + headlineLabel.setWithJSON(headlineJSON, delegateObject: delegateObject, additionalData: additionalData) + let bodyJSON = json?.optionalDictionaryForKey("body") + messageLabel.setWithJSON(bodyJSON, delegateObject: delegateObject, additionalData: additionalData) + } + + open override func reset() { + super.reset() + headlineLabel.styleH2(true) + messageLabel.styleB2(true) + } + + public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 58 + } +} + diff --git a/MVMCoreUI/Molecules/ModuleMolecule.swift b/MVMCoreUI/Molecules/ModuleMolecule.swift index 3478c9ab..7781021f 100644 --- a/MVMCoreUI/Molecules/ModuleMolecule.swift +++ b/MVMCoreUI/Molecules/ModuleMolecule.swift @@ -10,11 +10,11 @@ import UIKit open class ModuleMolecule: ViewConstrainingView { - open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)? + open var moduleMolecule: (UIView & MVMCoreUIMoleculeViewProtocol)? open override func updateView(_ size: CGFloat) { super.updateView(size) - molecule?.updateView(size) + moduleMolecule?.updateView(size) } // MARK: - MVMCoreUIMoleculeViewProtocol @@ -26,26 +26,25 @@ open class ModuleMolecule: ViewConstrainingView { return } - if molecule == nil { + if moduleMolecule == nil { if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: module, delegateObject: delegateObject, constrainIfNeeded: true) { addSubview(moleculeView) NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: false).values)) - molecule = moleculeView + moduleMolecule = moleculeView } } else { - molecule?.setWithJSON(module, delegateObject: delegateObject, additionalData: additionalData) + moduleMolecule?.setWithJSON(module, delegateObject: delegateObject, additionalData: additionalData) } } open override func setAsMolecule() { super.setAsMolecule() - updateViewHorizontalDefaults = false - molecule?.setAsMolecule?() + moduleMolecule?.setAsMolecule?() } open override func reset() { super.reset() - molecule?.reset?() + moduleMolecule?.reset?() } public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { @@ -80,22 +79,22 @@ open class ModuleMolecule: ViewConstrainingView { // MARK: - MVMCoreUIViewConstrainingProtocol open override func useStandardConstraints() -> Bool { - return (molecule as? MVMCoreUIViewConstrainingProtocol)?.useStandardConstraints?() ?? true + return (moduleMolecule as? MVMCoreUIViewConstrainingProtocol)?.useStandardConstraints?() ?? true } open override func alignHorizontal(_ alignment: UIStackView.Alignment) { - (molecule as? MVMCoreUIViewConstrainingProtocol)?.alignHorizontal?(alignment) + (moduleMolecule as? MVMCoreUIViewConstrainingProtocol)?.alignHorizontal?(alignment) } open override func alignVertical(_ alignment: UIStackView.Alignment) { - (molecule as? MVMCoreUIViewConstrainingProtocol)?.alignVertical?(alignment) + (moduleMolecule as? MVMCoreUIViewConstrainingProtocol)?.alignVertical?(alignment) } open override func shouldSetHorizontalMargins(_ shouldSet: Bool) { - (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(shouldSet) + (moduleMolecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(shouldSet) } open override func shouldSetVerticalMargins(_ shouldSet: Bool) { - (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(shouldSet) + (moduleMolecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(shouldSet) } } diff --git a/MVMCoreUI/Molecules/StandardFooterView.swift b/MVMCoreUI/Molecules/StandardFooterView.swift index 21c70a7f..a135ccc0 100644 --- a/MVMCoreUI/Molecules/StandardFooterView.swift +++ b/MVMCoreUI/Molecules/StandardFooterView.swift @@ -8,103 +8,24 @@ import UIKit -public class StandardFooterView: ViewConstrainingView { - let twoButtonView = TwoButtonView(frame: .zero) - var textButton = MFTextButton(nil, constrainHeight: true, forWidth: MVMCoreUIUtility.getWidth()) - var spaceBetweenButtons: NSLayoutConstraint? - var leftConstraintTwoButton: NSLayoutConstraint? - var rightConstraintTwoButton: NSLayoutConstraint? - var leftConstraintTextButton: NSLayoutConstraint? - var rightConstraintTextButton: NSLayoutConstraint? - var centerAlignTextButton: NSLayoutConstraint? - private var heightConstraint: NSLayoutConstraint? - - public override func updateView(_ size: CGFloat) { - super.updateView(size) - twoButtonView.updateView(size) - textButton.updateView(size) - setSpacing() - } - - public override func setupView() { +open class StandardFooterView: ViewConstrainingView { + open override func setupView() { super.setupView() - guard subviews.count == 0 else { - return - } - translatesAutoresizingMaskIntoConstraints = false - backgroundColor = .clear - clipsToBounds = true - setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) - setContentCompressionResistancePriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) - - addSubview(twoButtonView) - addSubview(textButton) - - topPin = twoButtonView.topAnchor.constraint(equalTo: topAnchor, constant: PaddingDefaultVerticalSpacing) - topPin?.isActive = true - - spaceBetweenButtons = textButton.topAnchor.constraint(equalTo: twoButtonView.bottomAnchor, constant: PaddingTwo) - spaceBetweenButtons?.isActive = true - - leftConstraintTwoButton = twoButtonView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor) - leftConstraintTwoButton?.isActive = true - - rightConstraintTwoButton = layoutMarginsGuide.rightAnchor.constraint(equalTo: twoButtonView.rightAnchor) - rightConstraintTwoButton?.isActive = true - - leftConstraintTextButton = textButton.leftAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor) - leftConstraintTextButton?.isActive = true - - rightConstraintTextButton = layoutMarginsGuide.rightAnchor.constraint(greaterThanOrEqualTo: textButton.rightAnchor) - rightConstraintTextButton?.isActive = true - - centerAlignTextButton = textButton.centerXAnchor.constraint(equalTo: centerXAnchor) - centerAlignTextButton?.isActive = true - - bottomPin = bottomAnchor.constraint(equalTo: textButton.bottomAnchor, constant: PaddingDefaultVerticalSpacing) - bottomPin?.isActive = true - - heightConstraint = heightAnchor.constraint(equalToConstant: 0) + setupMoleculeFromJSON = true } - public func setSpacing() { - if !(twoButtonView.heightConstraint?.isActive ?? false) && textButton.title(for: UIControl.State.normal)?.count ?? 0 > 0 { - spaceBetweenButtons?.constant = PaddingTwo - show() - } else if !(twoButtonView.heightConstraint?.isActive ?? false) || textButton.title(for: UIControl.State.normal)?.count ?? 0 > 0 { - spaceBetweenButtons?.constant = 0 - show() - } else { - hide() - } - } - - public override func show() { - super.show() - heightConstraint?.isActive = false - topPin?.isActive = true - layoutIfNeeded() - } - - public override func hide() { - super.hide() - heightConstraint?.isActive = true - topPin?.isActive = false - layoutIfNeeded() - } - - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - twoButtonView.setWithJSON(json?.optionalDictionaryForKey("twoButtonView"), delegateObject: delegateObject, additionalData: additionalData) - textButton.setWithJSON(json?.optionalDictionaryForKey("textButton"), delegateObject: delegateObject, additionalData: additionalData) - } - - public override func reset() { - twoButtonView.reset() - textButton.reset() + (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(false) + (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(false) + shouldSetVerticalMargins(true) + shouldSetHorizontalMargins(true) } public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + if let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) { + return height + PaddingDefaultVerticalSpacing + PaddingDefaultVerticalSpacing + } return 42 } } diff --git a/MVMCoreUI/Molecules/StandardHeaderView.swift b/MVMCoreUI/Molecules/StandardHeaderView.swift index 2440656f..ff5b8538 100644 --- a/MVMCoreUI/Molecules/StandardHeaderView.swift +++ b/MVMCoreUI/Molecules/StandardHeaderView.swift @@ -9,126 +9,45 @@ import UIKit public class StandardHeaderView: ViewConstrainingView { - let headlineLabel = Label.commonLabelH2(true) - let messageLabel = Label.commonLabelB2(true) var separatorView: SeparatorView? - var spaceBetweenLabels: NSLayoutConstraint? - var leftConstraintTitle: NSLayoutConstraint? - var rightConstraintTitle: NSLayoutConstraint? - var leftConstraintMessage: NSLayoutConstraint? - var rightConstraintMessage: NSLayoutConstraint? - private var heightConstraint: NSLayoutConstraint? // MARK: - MVMCoreViewProtocol - public override func updateView(_ size: CGFloat) { + open override func updateView(_ size: CGFloat) { super.updateView(size) - headlineLabel.updateView(size) - messageLabel.updateView(size) separatorView?.updateView(size) - setSpacing() } public override func setupView() { super.setupView() - if separatorView == nil { - translatesAutoresizingMaskIntoConstraints = false - backgroundColor = .clear - clipsToBounds = true - - addSubview(headlineLabel) - addSubview(messageLabel) - - headlineLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) - messageLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) - setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) - - topPin = headlineLabel.topAnchor.constraint(equalTo: topAnchor, constant: PaddingDefaultVerticalSpacing) - topPin?.isActive = true - - spaceBetweenLabels = messageLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: PaddingTwo) - spaceBetweenLabels?.isActive = true - - leftConstraintTitle = headlineLabel.leftAnchor.constraint(equalTo: leftAnchor) - leftConstraintTitle?.isActive = true - - rightConstraintTitle = rightAnchor.constraint(equalTo: headlineLabel.rightAnchor) - rightConstraintTitle?.isActive = true - - leftConstraintMessage = messageLabel.leftAnchor.constraint(equalTo: leftAnchor) - leftConstraintMessage?.isActive = true - - rightConstraintMessage = rightAnchor.constraint(equalTo: messageLabel.rightAnchor) - rightConstraintMessage?.isActive = true - - bottomPin = bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: PaddingDefaultVerticalSpacing) - bottomPin?.isActive = true - - heightConstraint = heightAnchor.constraint(equalToConstant: 0) - heightConstraint?.priority = UILayoutPriority(rawValue: 950) - - if let separatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot, withHorizontalPadding: 0) { - separatorView.setAsHeavy() - addSubview(separatorView) - self.separatorView = separatorView - } + setupMoleculeFromJSON = true + if separatorView == nil, let separatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot, withHorizontalPadding: 0) { + separatorView.setAsHeavy() + addSubview(separatorView) + self.separatorView = separatorView } } - // MARK: - Constraining - public func setSpacing() { - if headlineLabel.hasText && messageLabel.hasText { - spaceBetweenLabels?.constant = PaddingTwo - show() - } else if headlineLabel.hasText || messageLabel.hasText { - spaceBetweenLabels?.constant = 0 - show() - } else { - hide() - } - } - - public override func show() { - super.show() - heightConstraint?.isActive = false - layoutIfNeeded() - } - - public override func hide() { - super.hide() - heightConstraint?.isActive = true - layoutIfNeeded() - } - public override func setLeftPinConstant(_ constant: CGFloat) { - leftConstraintTitle?.constant = constant - leftConstraintMessage?.constant = constant + super.setLeftPinConstant(constant) separatorView?.leftPin?.constant = constant } public override func setRightPinConstant(_ constant: CGFloat) { - rightConstraintTitle?.constant = constant - rightConstraintMessage?.constant = constant + super.setRightPinConstant(constant) separatorView?.rightPin?.constant = constant } // MARK: - MVMCoreUIMoleculeViewProtocol open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - if let colorString = json?.optionalStringForKey("contentColor") { - let color = UIColor.mfGet(forHex: colorString) - headlineLabel.textColor = color - messageLabel.textColor = color - separatorView?.backgroundColor = color - } + (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(false) + (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(false) + shouldSetVerticalMargins(true) + shouldSetHorizontalMargins(true) - let headlineJSON = json?.optionalDictionaryForKey("headline") - headlineLabel.setWithJSON(headlineJSON, delegateObject: delegateObject, additionalData: additionalData) - let bodyJSON = json?.optionalDictionaryForKey("body") - messageLabel.setWithJSON(bodyJSON, delegateObject: delegateObject, additionalData: additionalData) if let separatorJSON = json?.optionalDictionaryForKey("separator") { separatorView?.setWithJSON(separatorJSON, delegateObject: delegateObject, additionalData: additionalData) } - if separatorView?.isHidden ?? true { bottomPin?.constant = 0 } else { @@ -137,14 +56,15 @@ public class StandardHeaderView: ViewConstrainingView { } open override func reset() { - backgroundColor = .clear - headlineLabel.styleH2(true) - messageLabel.styleB2(true) + super.reset() separatorView?.setAsHeavy() separatorView?.show() } public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + if let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) { + return height + PaddingDefaultVerticalSpacing + PaddingDefaultVerticalSpacing + } return 121 } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index daeaf2dc..67279c6e 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -47,7 +47,8 @@ @"switch": Switch.class, @"image": MFLoadImageView.class, @"leftRightLabelView": LeftRightLabelView.class, - @"moduleMolecule": ModuleMolecule.class + @"moduleMolecule": ModuleMolecule.class, + @"headlineBody": HeadlineBody.class } mutableCopy]; }); return mapping; From 436e9035d24cb338d65ef4aea8a85d3b84b90a97 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 3 Jul 2019 13:21:52 -0400 Subject: [PATCH 2/2] resolve discussions --- MVMCoreUI/Atoms/Views/ViewConstrainingView.h | 2 +- MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 3 ++- MVMCoreUI/Molecules/StandardFooterView.swift | 2 +- MVMCoreUI/Molecules/StandardHeaderView.swift | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h index 9ec6c193..a98a181d 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h @@ -37,7 +37,7 @@ @property (weak, nullable, nonatomic) UIView *molecule; /// A flag for if we should add a molecule from json. -@property (nonatomic) BOOL setupMoleculeFromJSON; +@property (nonatomic) BOOL shouldSetupMoleculeFromJSON; // Returns an empty view + (nonnull ViewConstrainingView *)emptyView; diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index 093e1ecc..1f6b568f 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -341,7 +341,7 @@ [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; [self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; - if (self.setupMoleculeFromJSON && !self.molecule) { + if (self.shouldSetupMoleculeFromJSON && !self.molecule) { NSDictionary *moleculeJSON = [json dict:KeyMolecule]; if (moleculeJSON) { UIView *molecule = [[MVMCoreUIMoleculeMappingObject sharedMappingObject] createMoleculeForJSON:moleculeJSON delegateObject:delegateObject constrainIfNeeded:true]; @@ -349,6 +349,7 @@ [self insertSubview:molecule atIndex:0]; [self pinViewToSuperView:molecule]; } + self.molecule = molecule; } } if (self.molecule) { diff --git a/MVMCoreUI/Molecules/StandardFooterView.swift b/MVMCoreUI/Molecules/StandardFooterView.swift index a135ccc0..59f7c0a9 100644 --- a/MVMCoreUI/Molecules/StandardFooterView.swift +++ b/MVMCoreUI/Molecules/StandardFooterView.swift @@ -11,7 +11,7 @@ import UIKit open class StandardFooterView: ViewConstrainingView { open override func setupView() { super.setupView() - setupMoleculeFromJSON = true + shouldSetupMoleculeFromJSON = true } open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { diff --git a/MVMCoreUI/Molecules/StandardHeaderView.swift b/MVMCoreUI/Molecules/StandardHeaderView.swift index ff5b8538..bf6e2580 100644 --- a/MVMCoreUI/Molecules/StandardHeaderView.swift +++ b/MVMCoreUI/Molecules/StandardHeaderView.swift @@ -19,7 +19,7 @@ public class StandardHeaderView: ViewConstrainingView { public override func setupView() { super.setupView() - setupMoleculeFromJSON = true + shouldSetupMoleculeFromJSON = true if separatorView == nil, let separatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot, withHorizontalPadding: 0) { separatorView.setAsHeavy() addSubview(separatorView)