Merge branch 'develop' into feature/label_hero_character

This commit is contained in:
Kevin G Christiano 2019-09-23 14:28:42 -04:00
commit 96e5f47dd0
12 changed files with 161 additions and 34 deletions

View File

@ -42,6 +42,7 @@
D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* StandardFooterView.swift */; }; D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* StandardFooterView.swift */; };
D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */; }; D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */; };
D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */; };
D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */; }; D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */; };
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */; }; D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */; };
D282AACB2243C61700C46919 /* ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AACA2243C61700C46919 /* ButtonView.swift */; }; D282AACB2243C61700C46919 /* ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AACA2243C61700C46919 /* ButtonView.swift */; };
@ -226,6 +227,7 @@
D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = "<group>"; }; D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = "<group>"; };
D274CA322236A78900B01B62 /* StandardFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardFooterView.swift; sourceTree = "<group>"; }; D274CA322236A78900B01B62 /* StandardFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardFooterView.swift; sourceTree = "<group>"; };
D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = "<group>"; }; D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = "<group>"; };
D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EyebrowHeadlineBodyLink.swift; sourceTree = "<group>"; };
D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFLoadImageView.swift; sourceTree = "<group>"; }; D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFLoadImageView.swift; sourceTree = "<group>"; };
D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFTransparentGIFView.swift; sourceTree = "<group>"; }; D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFTransparentGIFView.swift; sourceTree = "<group>"; };
D282AACA2243C61700C46919 /* ButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonView.swift; sourceTree = "<group>"; }; D282AACA2243C61700C46919 /* ButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonView.swift; sourceTree = "<group>"; };
@ -418,6 +420,7 @@
children = ( children = (
D2A638FC22CA98280052ED1F /* HeadlineBody.swift */, D2A638FC22CA98280052ED1F /* HeadlineBody.swift */,
D22479952316AF6D003FCCF9 /* HeadlineBodyTextButton.swift */, D22479952316AF6D003FCCF9 /* HeadlineBodyTextButton.swift */,
D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */,
); );
path = VerticalCombinationViews; path = VerticalCombinationViews;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1067,6 +1070,7 @@
D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */,
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */,
D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */,
D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */,
D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */,
0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */, 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */,
D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */, D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */,

View File

@ -76,7 +76,7 @@ import UIKit
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
translatesAutoresizingMaskIntoConstraints = false translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .mfSilver() backgroundColor = .mfLightSilver()
clipsToBounds = true clipsToBounds = true
if thicknessConstraint == nil { if thicknessConstraint == nil {
thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight) thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight)
@ -84,6 +84,12 @@ import UIKit
} }
} }
open override func reset() {
super.reset()
backgroundColor = .mfLightSilver()
progressList = nil
}
override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
thicknessConstraint?.constant = json?.optionalCGFloatForKey("thickness") ?? defaultHeight thicknessConstraint?.constant = json?.optionalCGFloatForKey("thickness") ?? defaultHeight

View File

@ -70,7 +70,7 @@ import Foundation
thickness = 8 thickness = 8
progress = 0 progress = 0
progressTintColor = UIColor.mfCerulean() progressTintColor = UIColor.mfCerulean()
trackTintColor = UIColor.mfSilver() trackTintColor = UIColor.mfLightSilver()
} }
public static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { public static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {

View File

@ -34,6 +34,9 @@
@property (nonatomic) BOOL updateViewHorizontalDefaults; @property (nonatomic) BOOL updateViewHorizontalDefaults;
@property (nonatomic) BOOL updateViewVerticalDefaults; @property (nonatomic) BOOL updateViewVerticalDefaults;
@property (nonatomic) CGFloat topMarginPadding;
@property (nonatomic) CGFloat bottomMarginPadding;
/// A molecule if we constrain one. /// A molecule if we constrain one.
@property (weak, nullable, nonatomic) UIView <MVMCoreUIMoleculeViewProtocol>*molecule; @property (weak, nullable, nonatomic) UIView <MVMCoreUIMoleculeViewProtocol>*molecule;

View File

@ -304,18 +304,15 @@
[super setupView]; [super setupView];
self.translatesAutoresizingMaskIntoConstraints = NO; self.translatesAutoresizingMaskIntoConstraints = NO;
self.backgroundColor = [UIColor clearColor]; self.backgroundColor = [UIColor clearColor];
self.topMarginPadding = PaddingDefaultVerticalSpacing3;
self.bottomMarginPadding = PaddingDefaultVerticalSpacing3;
[MVMCoreUIUtility setMarginsForView:self leading:0 top:0 trailing:0 bottom:0]; [MVMCoreUIUtility setMarginsForView:self leading:0 top:0 trailing:0 bottom:0];
} }
- (void)updateView:(CGFloat)size { - (void)updateView:(CGFloat)size {
[super updateView:size]; [super updateView:size];
if ([self.constrainedView respondsToSelector:@selector(updateView:)]) { [self.molecule updateView:size];
[((id<MVMCoreViewProtocol>)self.constrainedView) updateView:size]; [MFStyler setMarginsForView:self size:size defaultHorizontal:self.updateViewHorizontalDefaults top:(self.updateViewVerticalDefaults ? self.topMarginPadding : 0) bottom:(self.updateViewVerticalDefaults ? self.bottomMarginPadding : 0)];
}
if (self.molecule != self.constrainedView) {
[self.molecule updateView:size];
}
[MFStyler setDefaultMarginsForView:self size:size horizontal:self.updateViewHorizontalDefaults vertical:self.updateViewVerticalDefaults];
UIEdgeInsets margins = [MVMCoreUIUtility getMarginsForView:self]; UIEdgeInsets margins = [MVMCoreUIUtility getMarginsForView:self];
if (self.updateViewHorizontalDefaults) { if (self.updateViewHorizontalDefaults) {
[self setLeftPinConstant:margins.left]; [self setLeftPinConstant:margins.left];
@ -344,6 +341,8 @@
[super reset]; [super reset];
self.updateViewHorizontalDefaults = NO; self.updateViewHorizontalDefaults = NO;
self.updateViewVerticalDefaults = NO; self.updateViewVerticalDefaults = NO;
self.topMarginPadding = PaddingDefaultVerticalSpacing3;
self.bottomMarginPadding = PaddingDefaultVerticalSpacing3;
if ([self.molecule respondsToSelector:@selector(alignment)]) { if ([self.molecule respondsToSelector:@selector(alignment)]) {
[self alignHorizontal:[(UIView <MVMCoreUIViewConstrainingProtocol> *)self.molecule alignment]]; [self alignHorizontal:[(UIView <MVMCoreUIViewConstrainingProtocol> *)self.molecule alignment]];
} }
@ -354,8 +353,10 @@
} }
- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
[super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; // Only treated as a container if we are constraining a molecule.
if (!self.constrainedView) {
[super setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
}
[self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; [self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
if (self.shouldSetupMoleculeFromJSON) { if (self.shouldSetupMoleculeFromJSON) {
NSDictionary *moleculeJSON = [json dict:KeyMolecule]; NSDictionary *moleculeJSON = [json dict:KeyMolecule];

View File

@ -19,7 +19,8 @@ import UIKit
} }
translatesAutoresizingMaskIntoConstraints = false translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false scrollView.translatesAutoresizingMaskIntoConstraints = false
addConstrainedView(scrollView) addSubview(scrollView)
pinView(toSuperView: scrollView)
scrollView.addSubview(contentView) scrollView.addSubview(contentView)
NSLayoutConstraint.constraintPinSubview(toSuperview: contentView) NSLayoutConstraint.constraintPinSubview(toSuperview: contentView)
let constraint = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 1.0) let constraint = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 1.0)

View File

@ -11,6 +11,8 @@ import UIKit
open class StandardFooterView: ViewConstrainingView { open class StandardFooterView: ViewConstrainingView {
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
topMarginPadding = PaddingDefaultVerticalSpacing
bottomMarginPadding = PaddingDefaultVerticalSpacing
shouldSetupMoleculeFromJSON = true shouldSetupMoleculeFromJSON = true
updateViewVerticalDefaults = true updateViewVerticalDefaults = true
updateViewHorizontalDefaults = true updateViewHorizontalDefaults = true

View File

@ -22,6 +22,8 @@ public class StandardHeaderView: ViewConstrainingView {
shouldSetupMoleculeFromJSON = true shouldSetupMoleculeFromJSON = true
updateViewVerticalDefaults = true updateViewVerticalDefaults = true
updateViewHorizontalDefaults = true updateViewHorizontalDefaults = true
topMarginPadding = PaddingDefaultVerticalSpacing
bottomMarginPadding = PaddingDefaultVerticalSpacing
if separatorView == nil, let separatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot, withHorizontalPadding: 0) { if separatorView == nil, let separatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot, withHorizontalPadding: 0) {
separatorView.setAsHeavy() separatorView.setAsHeavy()
addSubview(separatorView) addSubview(separatorView)
@ -54,6 +56,8 @@ public class StandardHeaderView: ViewConstrainingView {
open override func reset() { open override func reset() {
super.reset() super.reset()
topMarginPadding = PaddingDefaultVerticalSpacing
bottomMarginPadding = PaddingDefaultVerticalSpacing
separatorView?.setAsHeavy() separatorView?.setAsHeavy()
separatorView?.show() separatorView?.show()
} }

View File

@ -0,0 +1,70 @@
//
// EyebrowHeadlineBodyLink.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 9/23/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class EyebrowHeadlineBodyLink: ViewConstrainingView {
let stack = MoleculeStackView(frame: .zero)
let eyebrow = Label.commonLabelB3(true)
let headline = Label.commonLabelB1(true)
let body = Label.commonLabelB2(true)
let link = MFTextButton(nil, constrainHeight: false, forWidth: MVMCoreUIUtility.getWidth())
// MARK: - MFViewProtocol
open override func setupView() {
super.setupView()
guard stack.superview == nil else {
return
}
stack.spacing = 0
stack.updateViewHorizontalDefaults = false
addSubview(stack)
pinView(toSuperView: stack)
stack.addStackItem(StackItem(with: eyebrow), lastItem: false)
stack.addStackItem(StackItem(with: headline), lastItem: false)
stack.addStackItem(StackItem(with: body), lastItem: false)
// To visually take into account the extra padding in the intrinsic content of a button.
let stackItem = StackItem(with: link)
stackItem.spacing = -6
stack.addStackItem(stackItem, lastItem: true)
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
// MARK: - MVMCoreUIMoleculeViewProtocol
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
eyebrow.setWithJSON(json?.optionalDictionaryForKey("eyebrow"), delegateObject: delegateObject, additionalData: additionalData)
stack.items[0].gone = !eyebrow.hasText
headline.setWithJSON(json?.optionalDictionaryForKey("headline"), delegateObject: delegateObject, additionalData: additionalData)
stack.items[1].gone = !headline.hasText
body.setWithJSON(json?.optionalDictionaryForKey("body"), delegateObject: delegateObject, additionalData: additionalData)
stack.items[2].gone = !body.hasText
link.setWithJSON(json?.optionalDictionaryForKey("link"), delegateObject: delegateObject, additionalData: additionalData)
stack.items[3].gone = link.titleLabel?.text?.count ?? 0 == 0
stack.restack()
}
open override func reset() {
super.reset()
stack.reset()
stack.spacing = 0
stack.updateViewHorizontalDefaults = false
eyebrow.styleB3(true)
headline.styleB1(true)
body.styleB2(true)
}
public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return 65
}
}

View File

@ -32,6 +32,8 @@ open class HeadlineBody: ViewConstrainingView {
stylePageHeader() stylePageHeader()
case "item": case "item":
styleListItem() styleListItem()
case "itemHeader":
styleListItemDivider()
default: break default: break
} }
} }
@ -53,6 +55,12 @@ open class HeadlineBody: ViewConstrainingView {
messageLabel.styleB2(true) messageLabel.styleB2(true)
spaceBetweenLabelsConstant = 0 spaceBetweenLabelsConstant = 0
} }
func styleListItemDivider() {
headlineLabel.styleH3(true)
messageLabel.styleB2(true)
spaceBetweenLabelsConstant = 0
}
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) { open override func updateView(_ size: CGFloat) {
@ -80,10 +88,9 @@ open class HeadlineBody: ViewConstrainingView {
headlineLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) headlineLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical)
messageLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) messageLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical)
setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) view.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical)
topPin = headlineLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 0) headlineLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
topPin?.isActive = true
spaceBetweenLabels = messageLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: spaceBetweenLabelsConstant) spaceBetweenLabels = messageLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: spaceBetweenLabelsConstant)
spaceBetweenLabels?.isActive = true spaceBetweenLabels?.isActive = true
@ -100,8 +107,7 @@ open class HeadlineBody: ViewConstrainingView {
rightConstraintMessage = view.rightAnchor.constraint(equalTo: messageLabel.rightAnchor) rightConstraintMessage = view.rightAnchor.constraint(equalTo: messageLabel.rightAnchor)
rightConstraintMessage?.isActive = true rightConstraintMessage?.isActive = true
bottomPin = view.bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 0) view.bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 0).isActive = true
bottomPin?.isActive = true
} }
// MARK: - Constraining // MARK: - Constraining

View File

@ -14,25 +14,27 @@ public class StackItem {
var percentage: Int? var percentage: Int?
var verticalAlignment: UIStackView.Alignment? var verticalAlignment: UIStackView.Alignment?
var horizontalAlignment: UIStackView.Alignment? var horizontalAlignment: UIStackView.Alignment?
var gone = false
init(with view: UIView) { init(with view: UIView) {
self.view = view self.view = view
} }
init(with view: UIView, json: [AnyHashable: Any]) { init(with view: UIView, json: [AnyHashable: Any]?) {
self.view = view self.view = view
update(with: json) update(with: json)
} }
func update(with json: [AnyHashable: Any]) { func update(with json: [AnyHashable: Any]?) {
spacing = json.optionalCGFloatForKey("spacing") gone = json?.boolForKey("gone") ?? (json == nil)
percentage = json["percent"] as? Int spacing = json?.optionalCGFloatForKey("spacing")
if let alignment = json.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"verticalAlignment"]) { percentage = json?["percent"] as? Int
if let alignment = json?.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"verticalAlignment"]) {
verticalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill) verticalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill)
} else { } else {
verticalAlignment = nil verticalAlignment = nil
} }
if let alignment = json.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"horizontalAlignment"]) { if let alignment = json?.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"horizontalAlignment"]) {
horizontalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill) horizontalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill)
} else { } else {
horizontalAlignment = nil horizontalAlignment = nil
@ -84,11 +86,13 @@ public class MoleculeStackView: ViewConstrainingView {
/// Restacks the existing items. /// Restacks the existing items.
func restack() { func restack() {
MVMCoreUIStackableViewController.remove(contentView.subviews) setWithStackItems(items)
let stackItems = items }
items.removeAll()
for (index, item) in stackItems.enumerated() { /// Removes all stack items views from the view.
addStackItem(item, lastItem: index == stackItems.count - 1) func removeAllItemViews() {
for item in items {
item.view.removeFromSuperview()
} }
} }
@ -144,7 +148,7 @@ public class MoleculeStackView: ViewConstrainingView {
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
let previousJSON = self.json let previousJSON = self.json
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
MVMCoreUIStackableViewController.remove(contentView.subviews) removeAllItemViews()
// If the items in the stack are the same, just update previous items instead of re-allocating. // If the items in the stack are the same, just update previous items instead of re-allocating.
var items: [StackItem]? var items: [StackItem]?
@ -238,6 +242,10 @@ public class MoleculeStackView: ViewConstrainingView {
/// Adds the stack item to the stack. /// Adds the stack item to the stack.
func addStackItem(_ stackItem: StackItem, lastItem: Bool) { func addStackItem(_ stackItem: StackItem, lastItem: Bool) {
guard !stackItem.gone else {
items.append(stackItem)
return
}
let view = stackItem.view let view = stackItem.view
contentView.addSubview(view) contentView.addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false view.translatesAutoresizingMaskIntoConstraints = false
@ -249,10 +257,13 @@ public class MoleculeStackView: ViewConstrainingView {
view.alignHorizontal?(horizontalAlignment) view.alignHorizontal?(horizontalAlignment)
view.alignVertical?(verticalAlignment) view.alignVertical?(verticalAlignment)
} }
let first = items.first { !$0.gone } == nil
if axis == .vertical { if axis == .vertical {
if items.count == 0 { if first {
pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0) pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0)
} else if let previousView = items.last?.view { } else if let previousView = items.last(where: { stackItem in
return !stackItem.gone
})?.view {
_ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: true) _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: true)
} }
pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0)
@ -264,10 +275,12 @@ public class MoleculeStackView: ViewConstrainingView {
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
} }
} else { } else {
if items.count == 0 { if first {
// First horizontal item has no spacing by default unless told otherwise. // First horizontal item has no spacing by default unless told otherwise.
pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0) pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0)
} else if let previousView = items.last?.view { } else if let previousView = items.last(where: { stackItem in
return !stackItem.gone
})?.view {
_ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: false) _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: false)
} }
pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0)
@ -281,4 +294,20 @@ public class MoleculeStackView: ViewConstrainingView {
} }
items.append(stackItem) items.append(stackItem)
} }
func setWithStackItems(_ items: [StackItem]) {
removeAllItemViews()
self.items.removeAll()
var previousPresentItem: StackItem? = nil
for item in items {
if !item.gone {
previousPresentItem = item
}
addStackItem(item, lastItem: false)
}
if let lastView = previousPresentItem?.view {
let attribute: NSLayoutConstraint.Attribute = axis == .vertical ? .bottom : .right
pinView(contentView, toView: lastView, attribute: attribute, relation: .equal, priority: .required, constant: 0)
}
}
} }

View File

@ -60,7 +60,8 @@
@"headlineBodySwitch": HeadlineBodySwitch.class, @"headlineBodySwitch": HeadlineBodySwitch.class,
@"headlineBodyTextButton": HeadlineBodyTextButton.class, @"headlineBodyTextButton": HeadlineBodyTextButton.class,
@"headlineBodyTextButtonSwitch": HeadlineBodyTextButtonSwitch.class, @"headlineBodyTextButtonSwitch": HeadlineBodyTextButtonSwitch.class,
@"tabsListItem": TabsTableViewCell.class @"tabsListItem": TabsTableViewCell.class,
@"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class
} mutableCopy]; } mutableCopy];
}); });
return mapping; return mapping;