Collection changes
This commit is contained in:
parent
1ec11d9006
commit
b0be1dbce3
@ -210,6 +210,10 @@
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
|
||||
D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; };
|
||||
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
|
||||
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */; };
|
||||
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */; };
|
||||
D21B7F75243BAC8900051ABF /* CarouselItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F74243BAC8900051ABF /* CarouselItem.swift */; };
|
||||
D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F76243BB70700051ABF /* MoleculeCollectionItemModel.swift */; };
|
||||
D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; };
|
||||
D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479892314445E003FCCF9 /* LabelToggle.swift */; };
|
||||
D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224798B231450C8003FCCF9 /* HeadlineBodyToggle.swift */; };
|
||||
@ -242,6 +246,9 @@
|
||||
D260D7B122D65BDD007E7233 /* MVMCoreUIPageControl.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */; };
|
||||
D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */; };
|
||||
D264FA8E243BCD9A00D98315 /* CollectionTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */; };
|
||||
D264FA90243BCE6800D98315 /* ThreeLayerCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FA8F243BCE6800D98315 /* ThreeLayerCollectionViewController.swift */; };
|
||||
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; };
|
||||
D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; };
|
||||
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */; };
|
||||
@ -608,6 +615,10 @@
|
||||
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = "<group>"; };
|
||||
D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = "<group>"; };
|
||||
D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
||||
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemModelProtocol.swift; sourceTree = "<group>"; };
|
||||
D21B7F74243BAC8900051ABF /* CarouselItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItem.swift; sourceTree = "<group>"; };
|
||||
D21B7F76243BB70700051ABF /* MoleculeCollectionItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeCollectionItemModel.swift; sourceTree = "<group>"; };
|
||||
D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = "<group>"; };
|
||||
D22479892314445E003FCCF9 /* LabelToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggle.swift; sourceTree = "<group>"; };
|
||||
D224798B231450C8003FCCF9 /* HeadlineBodyToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyToggle.swift; sourceTree = "<group>"; };
|
||||
@ -640,6 +651,9 @@
|
||||
D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPageControl.h; sourceTree = "<group>"; };
|
||||
D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIPageControl.m; sourceTree = "<group>"; };
|
||||
D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = "<group>"; };
|
||||
D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionTemplateModel.swift; sourceTree = "<group>"; };
|
||||
D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionTemplate.swift; sourceTree = "<group>"; };
|
||||
D264FA8F243BCE6800D98315 /* ThreeLayerCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerCollectionViewController.swift; sourceTree = "<group>"; };
|
||||
D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = "<group>"; };
|
||||
D274CA322236A78900B01B62 /* FooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterView.swift; sourceTree = "<group>"; };
|
||||
@ -1236,8 +1250,6 @@
|
||||
D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */,
|
||||
01EB368923609801006832FA /* MoleculeListItemModel.swift */,
|
||||
01509D8E2327EC6F00EF99AA /* MoleculeTableViewCell.swift */,
|
||||
012A88C1238D7BCA00FE3DA1 /* CarouselItemModel.swift */,
|
||||
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */,
|
||||
D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */,
|
||||
D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */,
|
||||
D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */,
|
||||
@ -1249,6 +1261,11 @@
|
||||
D260105E23D0BFFC00764D80 /* StackItem.swift */,
|
||||
01EB368A23609801006832FA /* MoleculeStackItemModel.swift */,
|
||||
D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */,
|
||||
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */,
|
||||
D21B7F76243BB70700051ABF /* MoleculeCollectionItemModel.swift */,
|
||||
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */,
|
||||
012A88C1238D7BCA00FE3DA1 /* CarouselItemModel.swift */,
|
||||
D21B7F74243BAC8900051ABF /* CarouselItem.swift */,
|
||||
);
|
||||
path = Items;
|
||||
sourceTree = "<group>";
|
||||
@ -1403,6 +1420,8 @@
|
||||
942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */,
|
||||
014AA72A23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift */,
|
||||
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */,
|
||||
D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */,
|
||||
D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */,
|
||||
);
|
||||
path = Templates;
|
||||
sourceTree = "<group>";
|
||||
@ -1458,6 +1477,7 @@
|
||||
D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */,
|
||||
D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */,
|
||||
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */,
|
||||
D264FA8F243BCE6800D98315 /* ThreeLayerCollectionViewController.swift */,
|
||||
D2C521A823EDE79E00CA2634 /* ViewController.swift */,
|
||||
D2A92881241AAB67004E01C6 /* ScrollingViewController.swift */,
|
||||
D2A92883241ACB25004E01C6 /* ProgrammaticScrollViewController.swift */,
|
||||
@ -1757,6 +1777,7 @@
|
||||
D2B18B802360945C00A9AEDC /* View.swift */,
|
||||
0AE14F63238315D2005417F8 /* TextField.swift */,
|
||||
D2755D7A23689C7500485468 /* TableViewCell.swift */,
|
||||
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */,
|
||||
0A5D59C323AD488600EFD9E9 /* Protocols */,
|
||||
);
|
||||
path = BaseClasses;
|
||||
@ -2005,6 +2026,7 @@
|
||||
D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */,
|
||||
012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */,
|
||||
BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */,
|
||||
D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */,
|
||||
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */,
|
||||
011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */,
|
||||
D260106323D0C05000764D80 /* StackItemModel.swift in Sources */,
|
||||
@ -2022,6 +2044,7 @@
|
||||
0A21DB91235E0EDB00C160A2 /* DigitBox.swift in Sources */,
|
||||
D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */,
|
||||
D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */,
|
||||
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */,
|
||||
D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */,
|
||||
C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */,
|
||||
D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */,
|
||||
@ -2076,6 +2099,7 @@
|
||||
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
|
||||
5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */,
|
||||
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
|
||||
D264FA8E243BCD9A00D98315 /* CollectionTemplate.swift in Sources */,
|
||||
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */,
|
||||
94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */,
|
||||
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
|
||||
@ -2203,6 +2227,7 @@
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */,
|
||||
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */,
|
||||
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
||||
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
|
||||
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
|
||||
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
|
||||
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
|
||||
@ -2229,10 +2254,12 @@
|
||||
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */,
|
||||
C003506123AA94CD00B6AC29 /* Button.swift in Sources */,
|
||||
DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */,
|
||||
D264FA90243BCE6800D98315 /* ThreeLayerCollectionViewController.swift in Sources */,
|
||||
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */,
|
||||
0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */,
|
||||
BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */,
|
||||
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */,
|
||||
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */,
|
||||
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
|
||||
@ -2262,6 +2289,7 @@
|
||||
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */,
|
||||
0105618D224BBE7700E1557D /* FormValidator.swift in Sources */,
|
||||
01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */,
|
||||
D21B7F75243BAC8900051ABF /* CarouselItem.swift in Sources */,
|
||||
D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */,
|
||||
C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */,
|
||||
8D3BA9BD2433787000D341BA /* ListThreeColumnInternationalDataDividerModel.swift in Sources */,
|
||||
|
||||
@ -9,22 +9,20 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
@objcMembers public class CarouselItemModel: MoleculeContainerModel, CarouselItemModelProtocol {
|
||||
public static var identifier: String = "carouselItem"
|
||||
public var backgroundColor: Color?
|
||||
@objcMembers public class CarouselItemModel: MoleculeCollectionItemModel, CarouselItemModelProtocol {
|
||||
public override class var identifier: String {
|
||||
return "carouselItem"
|
||||
}
|
||||
public var peakingUI: Bool?
|
||||
public var peakingArrowColor: Color?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case peakingUI
|
||||
case peakingArrowColor
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
peakingUI = try typeContainer.decodeIfPresent(Bool.self, forKey: .peakingUI)
|
||||
peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor)
|
||||
try super.init(from: decoder)
|
||||
@ -33,8 +31,6 @@ import Foundation
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(peakingUI, forKey: .peakingUI)
|
||||
try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor)
|
||||
}
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
//
|
||||
// CollectionItemModelProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/6/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol CollectionItemModelProtocol: ContainerModelProtocol {
|
||||
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
//
|
||||
// MoleculeCollectionItemModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/6/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
@objcMembers open class MoleculeCollectionItemModel: CollectionItemModelProtocol, MoleculeModelProtocol {
|
||||
open class var identifier: String {
|
||||
return "collectionItem"
|
||||
}
|
||||
open var molecule: MoleculeModelProtocol
|
||||
public var backgroundColor: Color?
|
||||
|
||||
public var horizontalAlignment: UIStackView.Alignment?
|
||||
public var verticalAlignment: UIStackView.Alignment?
|
||||
public var useHorizontalMargins: Bool?
|
||||
public var useVerticalMargins: Bool?
|
||||
public var topMarginPadding: CGFloat?
|
||||
public var bottomMarginPadding: CGFloat?
|
||||
|
||||
/// Defaults to set
|
||||
open func setDefaults() {
|
||||
if useHorizontalMargins == nil {
|
||||
useHorizontalMargins = true
|
||||
}
|
||||
if useVerticalMargins == nil {
|
||||
useVerticalMargins = true
|
||||
}
|
||||
if topMarginPadding == nil {
|
||||
topMarginPadding = PaddingDefault
|
||||
}
|
||||
if bottomMarginPadding == nil {
|
||||
bottomMarginPadding = PaddingDefault
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case molecule
|
||||
case backgroundColor
|
||||
}
|
||||
|
||||
public init(with moleculeModel: MoleculeModelProtocol) {
|
||||
molecule = moleculeModel
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
molecule = try typeContainer.decodeModel(codingKey: .molecule)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeModel(molecule, forKey: .molecule)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
}
|
||||
}
|
||||
@ -8,90 +8,15 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
open class MoleculeCollectionViewCell: UICollectionViewCell, MoleculeViewProtocol {
|
||||
|
||||
open var molecule: MoleculeViewProtocol?
|
||||
public let containerHelper = ContainerHelper()
|
||||
|
||||
// In updateView, will set padding to default.
|
||||
open var updateViewHorizontalDefaults = true
|
||||
open var updateViewVerticalDefaults = true
|
||||
|
||||
open var allowsPeaking = false
|
||||
var peakingLeftArrow = UIImageView(image: MVMCoreUIUtility.imageNamed("peakingRightArrow")?.withRenderingMode(.alwaysTemplate))
|
||||
var peakingRightArrow = UIImageView(image: MVMCoreUIUtility.imageNamed("peakingRightArrow")?.withRenderingMode(.alwaysTemplate))
|
||||
var peakingCover = MVMCoreUICommonViewsUtility.commonView()
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: .zero)
|
||||
setupView()
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
setupView()
|
||||
}
|
||||
|
||||
public func setupView() {
|
||||
guard peakingCover.superview == nil else {
|
||||
return
|
||||
}
|
||||
isAccessibilityElement = false
|
||||
contentView.isAccessibilityElement = false
|
||||
insetsLayoutMarginsFromSafeArea = false
|
||||
contentView.insetsLayoutMarginsFromSafeArea = false
|
||||
contentView.preservesSuperviewLayoutMargins = false
|
||||
|
||||
// Covers the card when peaking.
|
||||
peakingCover.backgroundColor = .white
|
||||
peakingCover.alpha = 0
|
||||
contentView.addSubview(peakingCover)
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: peakingCover)
|
||||
|
||||
// A small arrow on the next card for when peaking.
|
||||
let ratio: CGFloat = 0.015
|
||||
peakingLeftArrow.translatesAutoresizingMaskIntoConstraints = false
|
||||
peakingLeftArrow.alpha = 0
|
||||
peakingLeftArrow.tintColor = .black
|
||||
contentView.addSubview(peakingLeftArrow)
|
||||
peakingLeftArrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
|
||||
NSLayoutConstraint.scalingPinViewLeft(toSuper: peakingLeftArrow, ratio: ratio, anchor: contentView.widthAnchor)
|
||||
|
||||
peakingRightArrow.translatesAutoresizingMaskIntoConstraints = false
|
||||
peakingRightArrow.transform = CGAffineTransform(scaleX: -1, y: 1) // Flip
|
||||
peakingRightArrow.alpha = 0
|
||||
peakingRightArrow.tintColor = .black
|
||||
contentView.addSubview(peakingRightArrow)
|
||||
peakingRightArrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
|
||||
NSLayoutConstraint.scalingPinViewRight(toSuper: peakingRightArrow, ratio: ratio, anchor: contentView.widthAnchor)
|
||||
}
|
||||
|
||||
|
||||
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let collectionModel = model as? CarouselItemModel else { return }
|
||||
if let useHorizontalMargins = collectionModel.useHorizontalMargins {
|
||||
updateViewHorizontalDefaults = useHorizontalMargins
|
||||
}
|
||||
if let useVerticalMargins = collectionModel.useVerticalMargins {
|
||||
updateViewVerticalDefaults = useVerticalMargins
|
||||
}
|
||||
// Handles peaking.
|
||||
allowsPeaking = collectionModel.peakingUI ?? false
|
||||
if let peakingArrowColor = collectionModel.peakingArrowColor {
|
||||
let color = peakingArrowColor.uiColor
|
||||
peakingLeftArrow.tintColor = color
|
||||
peakingRightArrow.tintColor = color
|
||||
}
|
||||
|
||||
if let backgroundColor = collectionModel.backgroundColor {
|
||||
self.backgroundColor = backgroundColor.uiColor
|
||||
}
|
||||
open class MoleculeCollectionViewCell: CollectionViewCell {
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let collectionModel = model as? MoleculeCollectionItemModel else { return }
|
||||
if molecule == nil {
|
||||
if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(collectionModel.molecule, delegateObject: delegateObject, additionalData: additionalData) {
|
||||
contentView.insertSubview(moleculeView, at: 0)
|
||||
containerHelper.constrainView(moleculeView)
|
||||
molecule = moleculeView
|
||||
addMolecule(moleculeView)
|
||||
contentView.sendSubviewToBack(moleculeView)
|
||||
}
|
||||
} else {
|
||||
molecule?.set(with: collectionModel.molecule, delegateObject, additionalData)
|
||||
@ -102,39 +27,33 @@ open class MoleculeCollectionViewCell: UICollectionViewCell, MoleculeViewProtoco
|
||||
accessibilityElements = molecule.subviews
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
molecule?.reset()
|
||||
updateViewVerticalDefaults = true
|
||||
updateViewHorizontalDefaults = true
|
||||
backgroundColor = .white
|
||||
}
|
||||
|
||||
public class func nameForReuse(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
guard let molecule = (model as? CarouselItemModel)?.molecule,
|
||||
let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(molecule) else {
|
||||
return nil
|
||||
}
|
||||
return moleculeClass.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName
|
||||
open class func nameForReuse(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
guard let moleculeModel = (model as? MoleculeCollectionItemModel)?.molecule else { return "\(self)<>" }
|
||||
let className = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
|
||||
let moleculeName = className?.nameForReuse(with: moleculeModel, delegateObject) ?? moleculeModel.moleculeName
|
||||
return "\(self)<\(moleculeName)>"
|
||||
}
|
||||
|
||||
public func updateView(_ size: CGFloat) {
|
||||
(molecule as? MVMCoreViewProtocol)?.updateView(size)
|
||||
MFStyler.setDefaultMarginsFor(contentView, size: size, horizontal: updateViewHorizontalDefaults, vertical: updateViewVerticalDefaults)
|
||||
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||
guard let moleculeModel = (model as? MoleculeCollectionItemModel)?.molecule,
|
||||
let theClass = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
|
||||
else { return nil }
|
||||
|
||||
return theClass.requiredModules(with: moleculeModel, delegateObject, error: error)
|
||||
}
|
||||
|
||||
public func setPeaking(_ peaking: Bool, animated: Bool) {
|
||||
guard allowsPeaking else {
|
||||
return
|
||||
}
|
||||
let animation = {() in
|
||||
self.peakingRightArrow.alpha = peaking ? 1 : 0
|
||||
self.peakingLeftArrow.alpha = peaking ? 1 : 0
|
||||
self.peakingCover.alpha = peaking ? 0.5 : 0
|
||||
}
|
||||
if animated {
|
||||
UIView.animate(withDuration: 0.4, animations: animation)
|
||||
} else {
|
||||
animation()
|
||||
}
|
||||
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
guard let model = model as? MoleculeCollectionItemModel,
|
||||
let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(model.molecule),
|
||||
let height = classType.estimatedHeight(with: model.molecule, delegateObject)
|
||||
else { return 100 }
|
||||
|
||||
return height + (model.topMarginPadding ?? 0) + (model.bottomMarginPadding ?? 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,12 +52,11 @@ open class Carousel: View {
|
||||
|
||||
public var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
private var size: CGFloat?
|
||||
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
guard collectionView.superview == nil else {
|
||||
return
|
||||
}
|
||||
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
||||
collectionView.dataSource = self
|
||||
collectionView.delegate = self
|
||||
@ -73,6 +72,7 @@ open class Carousel: View {
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
self.size = size
|
||||
collectionView.collectionViewLayout.invalidateLayout()
|
||||
showPeaking(false)
|
||||
|
||||
@ -143,7 +143,7 @@ open class Carousel: View {
|
||||
}
|
||||
|
||||
/// Sets up the paging molecule
|
||||
open func setupPagingMolecule(_ molecule: CarouselPagingModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) {
|
||||
open func setupPagingMolecule(_ molecule: (CarouselPagingModelProtocol & MoleculeModelProtocol)?, delegateObject: MVMCoreUIDelegateObject?) {
|
||||
var pagingView: (UIView & MVMCoreUIPagingProtocol)? = nil
|
||||
if let molecule = molecule {
|
||||
pagingView = MoleculeObjectMapping.shared()?.createMolecule(molecule, delegateObject: delegateObject) as? (UIView & MVMCoreUIPagingProtocol)
|
||||
@ -208,15 +208,15 @@ open class Carousel: View {
|
||||
// Show overlay and arrow in peaking Cell
|
||||
let visibleItemsPaths = collectionView.indexPathsForVisibleItems.sorted { $0.row < $1.row }
|
||||
if let firstItem = visibleItemsPaths.first, firstItem.row != currentIndex {
|
||||
(collectionView.cellForItem(at: firstItem) as? MoleculeCollectionViewCell)?.setPeaking(true, animated: true)
|
||||
(collectionView.cellForItem(at: firstItem) as? CarouselItem)?.setPeaking(true, animated: true)
|
||||
}
|
||||
if let lastItem = visibleItemsPaths.last, lastItem.row != currentIndex {
|
||||
(collectionView.cellForItem(at: lastItem) as? MoleculeCollectionViewCell)?.setPeaking(true, animated: true)
|
||||
(collectionView.cellForItem(at: lastItem) as? CarouselItem)?.setPeaking(true, animated: true)
|
||||
}
|
||||
} else {
|
||||
// Hide peaking.
|
||||
for item in collectionView.visibleCells {
|
||||
(item as? MoleculeCollectionViewCell)?.setPeaking(false, animated: true)
|
||||
(item as? CarouselItem)?.setPeaking(false, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,10 +229,12 @@ open class Carousel: View {
|
||||
cell.accessibilityElementsHidden = false
|
||||
var array = cell.accessibilityElements
|
||||
|
||||
if let acc = pagingView?.accessibilityElements {
|
||||
array?.append(contentsOf: acc)
|
||||
} else {
|
||||
array?.append(pagingView!)
|
||||
if let pagingView = pagingView {
|
||||
if let acc = pagingView.accessibilityElements {
|
||||
array?.append(contentsOf: acc)
|
||||
} else {
|
||||
array?.append(pagingView)
|
||||
}
|
||||
}
|
||||
|
||||
self.accessibilityElements = array
|
||||
@ -244,12 +246,12 @@ open class Carousel: View {
|
||||
|
||||
extension Carousel: UICollectionViewDelegateFlowLayout {
|
||||
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
let itemWidth = collectionView.bounds.width * CGFloat(itemWidthPercent)
|
||||
let itemWidth = (size ?? collectionView.bounds.width) * CGFloat(itemWidthPercent)
|
||||
return CGSize(width: itemWidth, height: collectionView.bounds.height)
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
|
||||
(cell as? MoleculeCollectionViewCell)?.setPeaking(false, animated: false)
|
||||
(cell as? CarouselItem)?.setPeaking(false, animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +270,7 @@ extension Carousel: UICollectionViewDataSource {
|
||||
protocolCell.reset()
|
||||
protocolCell.set(with: moleculeInfo.molecule, delegateObject, nil)
|
||||
}
|
||||
(cell as? MVMCoreViewProtocol)?.updateView(collectionView.bounds.width)
|
||||
(cell as? MVMCoreViewProtocol)?.updateView(size ?? collectionView.bounds.width)
|
||||
setAccessiblity(cell, index: indexPath.row)
|
||||
return cell
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ import UIKit
|
||||
public var height: Float?
|
||||
public var itemWidthPercent: Float?
|
||||
public var itemAlignment: UICollectionView.ScrollPosition?
|
||||
public var pagingMolecule: CarouselPagingModelProtocol?
|
||||
public var pagingMolecule: (CarouselPagingModelProtocol & MoleculeModelProtocol)?
|
||||
|
||||
public init(molecules: [CarouselItemModel]){
|
||||
self.molecules = molecules
|
||||
@ -42,12 +42,12 @@ import UIKit
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.molecules = try typeContainer.decode([CarouselItemModel].self, forKey: .molecules)
|
||||
self.backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
self.spacing = try typeContainer.decode(Float.self, forKey: .spacing)
|
||||
self.border = try typeContainer.decode(Bool.self, forKey: .border)
|
||||
self.loop = try typeContainer.decode(Bool.self, forKey: .loop)
|
||||
self.height = try typeContainer.decode(Float.self, forKey: .height)
|
||||
self.itemWidthPercent = try typeContainer.decode(Float.self, forKey: .itemWidthPercent)
|
||||
self.itemAlignment = try typeContainer.decode(UICollectionView.ScrollPosition.self, forKey: .itemAlignment)
|
||||
self.spacing = try typeContainer.decodeIfPresent(Float.self, forKey: .spacing)
|
||||
self.border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border)
|
||||
self.loop = try typeContainer.decodeIfPresent(Bool.self, forKey: .loop)
|
||||
self.height = try typeContainer.decodeIfPresent(Float.self, forKey: .height)
|
||||
self.itemWidthPercent = try typeContainer.decodeIfPresent(Float.self, forKey: .itemWidthPercent)
|
||||
self.itemAlignment = try typeContainer.decodeIfPresent(UICollectionView.ScrollPosition.self, forKey: .itemAlignment)
|
||||
self.pagingMolecule = try typeContainer.decodeModelIfPresent(codingKey: .pagingMolecule)
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,6 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public protocol CarouselPagingModelProtocol: MoleculeModelProtocol {
|
||||
public protocol CarouselPagingModelProtocol {
|
||||
var position: Float? { get }
|
||||
}
|
||||
|
||||
15
MVMCoreUI/Atomic/Templates/CollectionTemplate.swift
Normal file
15
MVMCoreUI/Atomic/Templates/CollectionTemplate.swift
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// CollectionTemplate.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/6/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc open class CollectionTemplate: ThreeLayerCollectionViewController, TemplateProtocol {
|
||||
public typealias TemplateModel = CollectionTemplateModel
|
||||
public var templateModel: CollectionTemplateModel?
|
||||
|
||||
}
|
||||
67
MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift
Normal file
67
MVMCoreUI/Atomic/Templates/CollectionTemplateModel.swift
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// CollectionTemplateModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/6/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class CollectionTemplateModel: TemplateModel {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public override class var identifier: String {
|
||||
return "collection"
|
||||
}
|
||||
public var header: MoleculeModelProtocol?
|
||||
public var molecules: [CollectionItemModelProtocol & MoleculeModelProtocol]?
|
||||
public var footer: MoleculeModelProtocol?
|
||||
public var columns: Int?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(pageType: String, screenHeading: String?, molecules: [CollectionItemModelProtocol & MoleculeModelProtocol]) {
|
||||
super.init(pageType: pageType)
|
||||
self.screenHeading = screenHeading
|
||||
self.molecules = molecules
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case molecules
|
||||
case header
|
||||
case footer
|
||||
case columns
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules)
|
||||
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
|
||||
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
|
||||
columns = try typeContainer.decodeIfPresent(Int.self, forKey: .columns)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeModelsIfPresent(molecules, forKey: .molecules)
|
||||
try container.encodeModelIfPresent(header, forKey: .header)
|
||||
try container.encodeModelIfPresent(footer, forKey: .footer)
|
||||
try container.encodeIfPresent(columns, forKey: .columns)
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,10 +51,6 @@ import UIKit
|
||||
return molecule
|
||||
}
|
||||
|
||||
open override func spaceBetweenMiddleAndBottom() -> CGFloat? {
|
||||
return 0
|
||||
}
|
||||
|
||||
open override func spaceBetweenTopAndMiddle() -> CGFloat? {
|
||||
return 0
|
||||
}
|
||||
|
||||
77
MVMCoreUI/BaseClasses/CollectionViewCell.swift
Normal file
77
MVMCoreUI/BaseClasses/CollectionViewCell.swift
Normal file
@ -0,0 +1,77 @@
|
||||
//
|
||||
// CollectionViewCell.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/6/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCoreViewProtocol {
|
||||
|
||||
// Convenience helpers
|
||||
open var molecule: MoleculeViewProtocol?
|
||||
public let containerHelper = ContainerHelper()
|
||||
open var model: CollectionItemModelProtocol?
|
||||
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: .zero)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
private func initialSetup() {
|
||||
if !initialSetupPerformed {
|
||||
initialSetupPerformed = true
|
||||
setupView()
|
||||
}
|
||||
}
|
||||
|
||||
open func setupView() {
|
||||
isAccessibilityElement = false
|
||||
contentView.isAccessibilityElement = false
|
||||
insetsLayoutMarginsFromSafeArea = false
|
||||
contentView.insetsLayoutMarginsFromSafeArea = false
|
||||
contentView.preservesSuperviewLayoutMargins = false
|
||||
MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0)
|
||||
}
|
||||
|
||||
open func updateView(_ size: CGFloat) {
|
||||
containerHelper.updateViewMargins(contentView, model: model, size: size)
|
||||
DispatchQueue.main.async {
|
||||
print("\(self.contentView.directionalLayoutMargins.leading)")
|
||||
}
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
molecule?.reset()
|
||||
backgroundColor = .white
|
||||
}
|
||||
|
||||
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let model = model as? CollectionItemModelProtocol else { return }
|
||||
self.model = model
|
||||
|
||||
if let moleculeModel = model as? MoleculeModelProtocol,
|
||||
let backgroundColor = moleculeModel.backgroundColor {
|
||||
self.backgroundColor = backgroundColor.uiColor
|
||||
}
|
||||
|
||||
// align if needed.
|
||||
containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol)
|
||||
}
|
||||
|
||||
/// Convenience function. Adds the molecule to the view.
|
||||
open func addMolecule(_ molecule: MoleculeViewProtocol) {
|
||||
contentView.addSubview(molecule)
|
||||
containerHelper.constrainView(molecule)
|
||||
self.molecule = molecule
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,289 @@
|
||||
//
|
||||
// ThreeLayerCollectionViewController.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/6/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc open class ThreeLayerCollectionViewController: ScrollingViewController, UICollectionViewDataSource, UICollectionViewDelegate {
|
||||
public var collectionView: UICollectionView?
|
||||
|
||||
// The three main views
|
||||
private var topView: UIView?
|
||||
private var bottomView: UIView?
|
||||
private var headerView: UIView?
|
||||
private var footerView: UIView?
|
||||
private var safeAreaView: UIView?
|
||||
var useMargins: Bool = true
|
||||
public var bottomViewOutsideOfScrollArea: Bool = false
|
||||
private var topViewBottomConstraint: NSLayoutConstraint?
|
||||
private var bottomViewTopConstraint: NSLayoutConstraint?
|
||||
|
||||
//MARK: - MFViewController
|
||||
open override func updateViews() {
|
||||
super.updateViews()
|
||||
let width = view.bounds.width
|
||||
if let topView = topView as? MVMCoreViewProtocol {
|
||||
topView.updateView(width)
|
||||
//showHeader(width)
|
||||
}
|
||||
if let bottomView = bottomView as? MVMCoreViewProtocol {
|
||||
bottomView.updateView(width)
|
||||
//showFooter(width)
|
||||
}
|
||||
self.collectionView?.collectionViewLayout.invalidateLayout()
|
||||
}
|
||||
|
||||
open override func handleNewData() {
|
||||
super.handleNewData()
|
||||
//createViewForTableHeader()
|
||||
//createViewForTableFooter()
|
||||
collectionView?.reloadData()
|
||||
}
|
||||
|
||||
override open func viewDidLoad() {
|
||||
let collection = createCollectionView()
|
||||
collectionView = collection
|
||||
view.addSubview(collection)
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: collection)
|
||||
scrollView = collectionView
|
||||
|
||||
registerCells()
|
||||
|
||||
super.viewDidLoad()
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
//MARK: - Spacing
|
||||
// If both are subclassed to return a value, then the buttons will not be pinned towards the bottom because neither spacing would try to fill the screen.
|
||||
/// Space between the top view and the table sections, nil to fill. 0 default
|
||||
open func spaceBelowTopView() -> CGFloat? {
|
||||
return 0
|
||||
}
|
||||
|
||||
/// Space between the bottom view and the table sections, nil to fill. nil default
|
||||
open func spaceAboveBottomView() -> CGFloat? {
|
||||
return nil
|
||||
}
|
||||
|
||||
/// can override to return a minimum fill space.
|
||||
open func minimumFillSpace() -> CGFloat {
|
||||
return 0
|
||||
}
|
||||
|
||||
/*open override func updateViewConstraints() {
|
||||
super.updateViewConstraints()
|
||||
|
||||
guard let tableView = collectionView else { return }
|
||||
|
||||
let minimumSpace: CGFloat = minimumFillSpace()
|
||||
var currentSpace: CGFloat = 0
|
||||
var totalMinimumSpace: CGFloat = 0
|
||||
|
||||
var fillTop = false
|
||||
if spaceBelowTopView() == nil, headerView != nil {
|
||||
fillTop = true
|
||||
currentSpace += topViewBottomConstraint?.constant ?? 0
|
||||
totalMinimumSpace += minimumSpace
|
||||
}
|
||||
|
||||
var fillBottom = false
|
||||
if spaceAboveBottomView() == nil, !bottomViewOutsideOfScrollArea, footerView != nil {
|
||||
fillBottom = true
|
||||
currentSpace += bottomViewTopConstraint?.constant ?? 0
|
||||
totalMinimumSpace += minimumSpace
|
||||
}
|
||||
|
||||
guard fillTop || fillBottom else { return }
|
||||
|
||||
let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace)
|
||||
|
||||
// If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value.
|
||||
var currentSpaceForCompare: CGFloat = currentSpace
|
||||
if fillTop && bottomViewOutsideOfScrollArea {
|
||||
currentSpaceForCompare = currentSpace * 2;
|
||||
}
|
||||
|
||||
let width = view.bounds.width
|
||||
if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpaceForCompare, 0.1) {
|
||||
if fillTop && fillBottom {
|
||||
// space both
|
||||
let half = newSpace / 2
|
||||
topViewBottomConstraint?.constant = half
|
||||
bottomViewTopConstraint?.constant = half
|
||||
showHeader(width)
|
||||
showFooter(width)
|
||||
} else if fillTop {
|
||||
// Only top is spaced (half the size if the bottom view is out of the scroll because it needs to be sized as if there are two spacers but there is only one.
|
||||
if bottomViewOutsideOfScrollArea {
|
||||
topViewBottomConstraint?.constant = newSpace / 2
|
||||
} else {
|
||||
topViewBottomConstraint?.constant = newSpace
|
||||
}
|
||||
showHeader(width)
|
||||
} else if fillBottom {
|
||||
// Only bottom is spaced.
|
||||
bottomViewTopConstraint?.constant = newSpace
|
||||
showFooter(width)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Header Footer
|
||||
/// Gets the top view and adds it to a spacing view, headerView, and then calls showHeader.
|
||||
open func createViewForTableHeader() {
|
||||
let topView = viewForTop()
|
||||
self.topView = topView
|
||||
|
||||
let headerView = MVMCoreUICommonViewsUtility.commonView()
|
||||
headerView.addSubview(topView)
|
||||
topView.topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true
|
||||
topView.leftAnchor.constraint(equalTo: headerView.leftAnchor).isActive = true
|
||||
headerView.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true
|
||||
topViewBottomConstraint = headerView.bottomAnchor.constraint(equalTo: topView.bottomAnchor, constant: spaceBelowTopView() ?? 0)
|
||||
topViewBottomConstraint?.isActive = true
|
||||
self.headerView = headerView
|
||||
showHeader(nil)
|
||||
}
|
||||
|
||||
/// Gets the bottom view and adds it to a spacing view, footerView, and then calls showFooter.
|
||||
open func createViewForTableFooter() {
|
||||
let bottomView = viewForBottom()
|
||||
self.bottomView = bottomView
|
||||
|
||||
let footerView = MVMCoreUICommonViewsUtility.commonView()
|
||||
footerView.addSubview(bottomView)
|
||||
bottomViewTopConstraint = bottomView.topAnchor.constraint(equalTo: footerView.topAnchor, constant: spaceAboveBottomView() ?? 0)
|
||||
bottomViewTopConstraint?.isActive = true
|
||||
bottomView.leftAnchor.constraint(equalTo: footerView.leftAnchor).isActive = true
|
||||
footerView.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true
|
||||
footerView.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true
|
||||
self.footerView = footerView
|
||||
showFooter(nil)
|
||||
}
|
||||
|
||||
/// Takes the current headerView and adds it to the tableHeaderView
|
||||
func showHeader(_ sizingWidth: CGFloat?) {
|
||||
headerView?.removeFromSuperview()
|
||||
tableView?.tableHeaderView = nil
|
||||
guard let headerView = headerView else {
|
||||
return
|
||||
}
|
||||
|
||||
// This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout.
|
||||
headerView.setNeedsLayout()
|
||||
headerView.layoutIfNeeded()
|
||||
MVMCoreUIUtility.sizeView(toFit: headerView)
|
||||
let tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: MVMCoreUIUtility.getWidth(), height: headerView.frame.height))
|
||||
tableHeaderView.addSubview(headerView)
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: headerView)
|
||||
tableView?.tableHeaderView = tableHeaderView
|
||||
}
|
||||
|
||||
/// Takes the current footerView and adds it to the tableFooterView
|
||||
func showFooter(_ sizingWidth: CGFloat?) {
|
||||
footerView?.removeFromSuperview()
|
||||
safeAreaView?.removeFromSuperview()
|
||||
guard let footerView = footerView, let tableView = tableView else {
|
||||
return
|
||||
}
|
||||
|
||||
if bottomViewOutsideOfScrollArea {
|
||||
// put bottom view outside of scrolling area.
|
||||
bottomConstraint?.isActive = false
|
||||
view.addSubview(footerView)
|
||||
footerView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true
|
||||
footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
|
||||
view.rightAnchor.constraint(equalTo: footerView.rightAnchor).isActive = true
|
||||
view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true
|
||||
safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view)
|
||||
safeAreaView?.backgroundColor = bottomView?.backgroundColor
|
||||
} else {
|
||||
bottomConstraint?.isActive = true
|
||||
var y: CGFloat?
|
||||
if let tableFooterView = tableView.tableFooterView {
|
||||
// if footer already exists, use the same y location to avoid strange moving animation
|
||||
y = tableFooterView.frame.minY
|
||||
}
|
||||
|
||||
// This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout.
|
||||
MVMCoreUIUtility.sizeView(toFit: footerView)
|
||||
let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height))
|
||||
tableFooterView.addSubview(footerView)
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: footerView)
|
||||
tableView.tableFooterView = tableFooterView
|
||||
}
|
||||
}*/
|
||||
|
||||
//MARK: - Functions to subclass
|
||||
/// Subclass for a top view.
|
||||
open func viewForTop() -> UIView {
|
||||
let view = MVMCoreUICommonViewsUtility.commonView()
|
||||
// Small height is needed to stop apple from adding padding for grouped tables when no header.
|
||||
view.heightAnchor.constraint(equalToConstant: 1).isActive = true
|
||||
return view
|
||||
}
|
||||
|
||||
/// Subclass for a bottom view.
|
||||
open func viewForBottom() -> UIView {
|
||||
// Default spacing is standard when no buttons.
|
||||
let view = MVMCoreUICommonViewsUtility.commonView()
|
||||
view.heightAnchor.constraint(equalToConstant: PaddingDefaultVerticalSpacing).isActive = true
|
||||
return view
|
||||
}
|
||||
|
||||
open func createCollectionView() -> UICollectionView {
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
layout.scrollDirection = .vertical
|
||||
layout.minimumLineSpacing = 1
|
||||
layout.minimumInteritemSpacing = 0
|
||||
|
||||
let collection = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
||||
collection.translatesAutoresizingMaskIntoConstraints = false
|
||||
collection.dataSource = self
|
||||
collection.delegate = self
|
||||
collection.showsHorizontalScrollIndicator = false
|
||||
collection.backgroundColor = .white
|
||||
collection.isAccessibilityElement = false
|
||||
collection.contentInsetAdjustmentBehavior = .always
|
||||
return collection
|
||||
}
|
||||
|
||||
deinit {
|
||||
collectionView?.delegate = nil
|
||||
collectionView?.dataSource = nil
|
||||
}
|
||||
|
||||
//MARK: - Collection
|
||||
|
||||
public func registerCells() {
|
||||
collectionView?.register(MoleculeCollectionViewCell.self, forCellWithReuseIdentifier: "collectionItem")
|
||||
}
|
||||
|
||||
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
public func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionItem", for: indexPath) as! MoleculeCollectionViewCell
|
||||
let labelModel = LabelModel(text: "hello")
|
||||
let model = MoleculeCollectionItemModel(with: labelModel)
|
||||
cell.set(with: model, delegateObjectIVar, nil)
|
||||
return cell
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
return CGSize(width: 200, height: 200)
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
|
||||
(cell as? CarouselItem)?.setPeaking(false, animated: false)
|
||||
}
|
||||
}
|
||||
@ -24,7 +24,8 @@
|
||||
@"list" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]],
|
||||
@"threeLayer" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]],
|
||||
@"modalStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ModalMoleculeStackTemplate class]],
|
||||
@"modalList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ModalMoleculeListTemplate class]]
|
||||
@"modalList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ModalMoleculeListTemplate class]],
|
||||
@"collection" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[CollectionTemplate class]]
|
||||
} mutableCopy];
|
||||
});
|
||||
return viewControllerMapping;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user