diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 11c20e13..0eca06db 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; }; 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; + 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; @@ -207,6 +208,7 @@ 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = ""; }; + 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; @@ -570,6 +572,7 @@ D274CA322236A78900B01B62 /* StandardFooterView.swift */, D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */, + 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */, ); path = Molecules; sourceTree = ""; @@ -1014,6 +1017,7 @@ D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, + 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */, diff --git a/MVMCoreUI/Molecules/ActionDetailWithImage.swift b/MVMCoreUI/Molecules/ActionDetailWithImage.swift index ec91c479..86cee41b 100644 --- a/MVMCoreUI/Molecules/ActionDetailWithImage.swift +++ b/MVMCoreUI/Molecules/ActionDetailWithImage.swift @@ -14,10 +14,8 @@ import UIKit // MARK: - Outlets //------------------------------------------------------ - let header = HeadlineBody(frame: .zero) - let button = PrimaryButton.primaryTinyButton(false)! + let headlineBodyButton = HeadlineBodyButton(frame: .zero) let imageLoader = MFLoadImageView(pinnedEdges: .all) - let leftContainer = ViewConstrainingView.empty() //------------------------------------------------------ // MARK: - Properties @@ -30,7 +28,6 @@ import UIKit //------------------------------------------------------ var imageLeadingConstraint: NSLayoutConstraint? - var buttonTopConstraint: NSLayoutConstraint? //------------------------------------------------------ // MARK: - Initialization @@ -64,33 +61,20 @@ import UIKit setDefaultState() - addSubview(leftContainer) addSubview(imageLoader) - leftContainer.addSubview(header) - leftContainer.addSubview(button) + addSubview(headlineBodyButton) - leftContainer.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true - leftContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + headlineBodyButton.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true + headlineBodyButton.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true - layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: leftContainer.bottomAnchor).isActive = true - let leftContainerBottom = leftContainer.bottomAnchor.constraint(equalTo: bottomAnchor) + layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: headlineBodyButton.bottomAnchor).isActive = true + let leftContainerBottom = headlineBodyButton.bottomAnchor.constraint(equalTo: bottomAnchor) leftContainerBottom.priority = UILayoutPriority(249) leftContainerBottom.isActive = true - header.topAnchor.constraint(equalTo: leftContainer.topAnchor).isActive = true - header.leadingAnchor.constraint(equalTo: leftContainer.leadingAnchor).isActive = true - leftContainer.trailingAnchor.constraint(equalTo: header.trailingAnchor).isActive = true - - buttonTopConstraint = button.topAnchor.constraint(equalTo: header.bottomAnchor, constant: buttonHeaderPadding) - buttonTopConstraint?.isActive = true - - button.leadingAnchor.constraint(equalTo: leftContainer.leadingAnchor).isActive = true - leftContainer.bottomAnchor.constraint(equalTo: button.bottomAnchor).isActive = true - leftContainer.trailingAnchor.constraint(greaterThanOrEqualTo: button.trailingAnchor).isActive = true - imageLoader.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true layoutMarginsGuide.trailingAnchor.constraint(equalTo: imageLoader.trailingAnchor).isActive = true - imageLeadingConstraint = imageLoader.leadingAnchor.constraint(greaterThanOrEqualTo: leftContainer.trailingAnchor, constant: 16) + imageLeadingConstraint = imageLoader.leadingAnchor.constraint(greaterThanOrEqualTo: headlineBodyButton.trailingAnchor, constant: 16) imageLeadingConstraint?.isActive = true imageLoader.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor).isActive = true @@ -103,12 +87,8 @@ import UIKit override open func updateView(_ size: CGFloat) { super.updateView(size) - header.updateView(size) - button.updateView(size) + headlineBodyButton.updateView(size) imageLoader.updateView(size) - leftContainer.updateView(size) - - buttonTopConstraint?.constant = header.hasText() ? buttonHeaderPadding : 0 } public override static func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { @@ -121,10 +101,8 @@ import UIKit private func setDefaultState() { - header.headlineLabel.font = MFStyler.fontH3() - header.messageLabel.font = MFStyler.fontB3() - button.setAsSecondaryCustom() - button.isHidden = false + headlineBodyButton.headlineBody.headlineLabel.font = MFStyler.fontH3() + headlineBodyButton.headlineBody.messageLabel.font = MFStyler.fontB3() imageLoader.imageView.contentMode = .scaleAspectFit imageLoader.addSizeConstraintsForAspectRatio = true buttonHeaderPadding = PaddingTwo @@ -133,8 +111,7 @@ import UIKit override open func reset() { super.reset() - header.reset() - button.reset() + headlineBodyButton.reset() imageLeadingConstraint?.constant = 16 imageLoader.reset() setDefaultState() @@ -143,8 +120,7 @@ import UIKit open override func setAsMolecule() { super.setAsMolecule() - header.setAsMolecule() - button.setAsMolecule() + headlineBodyButton.setAsMolecule() imageLoader.setAsMolecule() setDefaultState() } @@ -153,18 +129,8 @@ import UIKit super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) guard let dictionary = json else { return } - - if let padding = dictionary.optionalCGFloatForKey("buttonHeaderPadding") { - buttonHeaderPadding = padding - } - header.setWithJSON(dictionary.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData) + headlineBodyButton.setWithJSON(dictionary.optionalDictionaryForKey("headlineBodyButton"), delegateObject: delegateObject, additionalData: additionalData) imageLoader.setWithJSON(dictionary.optionalDictionaryForKey("image"), delegateObject: delegateObject, additionalData: additionalData) - - if let buttonDictionary = dictionary.optionalDictionaryForKey("button") { - button.setWithJSON(buttonDictionary, delegateObject: delegateObject, additionalData: additionalData) - } else { - button.isHidden = true - } } } diff --git a/MVMCoreUI/Molecules/HeadlineBodyButton.swift b/MVMCoreUI/Molecules/HeadlineBodyButton.swift new file mode 100644 index 00000000..87efc9b6 --- /dev/null +++ b/MVMCoreUI/Molecules/HeadlineBodyButton.swift @@ -0,0 +1,135 @@ +// +// HeadlineBodyButton.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 9/12/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + + +@objcMembers open class HeadlineBodyButton: ViewConstrainingView { + //------------------------------------------------------ + // MARK: - Outlets + //------------------------------------------------------ + + let headlineBody = HeadlineBody(frame: .zero) + let button = PrimaryButton.primaryTinyButton(false)! + + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + + var buttonHeadlinePadding: CGFloat = 16 + + //------------------------------------------------------ + // MARK: - Constraints + //------------------------------------------------------ + + var buttonTopConstraint: NSLayoutConstraint? + + //------------------------------------------------------ + // MARK: - Initialization + //------------------------------------------------------ + + public init() { + super.init(frame: .zero) + } + + public override init(frame: CGRect) { + super.init(frame: frame) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + public convenience init(json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + self.init() + setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + } + + //------------------------------------------------------ + // MARK: - View Lifecycle + //------------------------------------------------------ + + override open func setupView() { + super.setupView() + + guard subviews.isEmpty else { return } + + defaultState() + + addSubview(headlineBody) + addSubview(button) + + headlineBody.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true + headlineBody.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + layoutMarginsGuide.trailingAnchor.constraint(equalTo: headlineBody.trailingAnchor).isActive = true + + buttonTopConstraint = button.topAnchor.constraint(equalTo: headlineBody.bottomAnchor, constant: buttonHeadlinePadding) + buttonTopConstraint?.isActive = true + + button.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + layoutMarginsGuide.bottomAnchor.constraint(equalTo: button.bottomAnchor).isActive = true + layoutMarginsGuide.trailingAnchor.constraint(greaterThanOrEqualTo: button.trailingAnchor).isActive = true + } + + override open func updateView(_ size: CGFloat) { + super.updateView(size) + + headlineBody.updateView(size) + button.updateView(size) + + buttonTopConstraint?.constant = headlineBody.hasText() && !button.isHidden ? buttonHeadlinePadding : 0 + } + + private func defaultState() { + + headlineBody.headlineLabel.font = MFStyler.fontH3() + headlineBody.messageLabel.font = MFStyler.fontB3() + button.setAsTiny(true) + button.setAsSecondaryCustom() + button.isHidden = false + buttonHeadlinePadding = PaddingTwo + } + + //------------------------------------------------------ + // MARK: - Molecule + //------------------------------------------------------ + + override open func reset() { + super.reset() + + headlineBody.reset() + button.reset() + defaultState() + } + + open override func setAsMolecule() { + super.setAsMolecule() + + headlineBody.setAsMolecule() + button.setAsMolecule() + defaultState() + } + + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + guard let dictionary = json else { return } + + if let padding = dictionary.optionalCGFloatForKey("buttonHeadlinePadding") { + buttonHeadlinePadding = padding + } + + headlineBody.setWithJSON(dictionary.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData) + + if let buttonDictionary = dictionary.optionalDictionaryForKey("button") { + button.setWithJSON(buttonDictionary, delegateObject: delegateObject, additionalData: additionalData) + } else { + button.isHidden = true + } + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 12c6fe35..bad7a224 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -61,6 +61,7 @@ @"headlineBodyTextButton": HeadlineBodyTextButton.class, @"headlineBodyTextButtonSwitch": HeadlineBodyTextButtonSwitch.class, @"tabsListItem": TabsTableViewCell.class, + @"headlineBodyButton": HeadlineBodyButton.class, @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class } mutableCopy]; });