This commit is contained in:
Pfeil, Scott Robert 2020-04-28 18:15:42 -04:00
commit 6b1d065263
26 changed files with 547 additions and 84 deletions

View File

@ -168,7 +168,7 @@
94CA227C24058534002D6750 /* VerizonNHGeTX-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */; }; 94CA227C24058534002D6750 /* VerizonNHGeTX-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */; };
94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */; }; 94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */; };
94CA227E24058534002D6750 /* VerizonNHGeDS-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */; }; 94CA227E24058534002D6750 /* VerizonNHGeDS-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */; };
94CA227F24058534002D6750 /* VerizonNHGeTX-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */; }; 94F6516D2437954100631BF9 /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94F6516C2437954100631BF9 /* Tabs.swift */; };
AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */; }; AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */; };
AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; };
AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */; }; AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */; };
@ -250,6 +250,8 @@
D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */; }; D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */; };
D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; }; D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; };
D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; };
D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D253BB9B245874F8002DE544 /* BGImageMolecule.swift */; };
D253BB9E2458751F002DE544 /* BGImageMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D253BB9D2458751F002DE544 /* BGImageMoleculeModel.swift */; };
D253BB8A24574CC5002DE544 /* StackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260106423D0CEA700764D80 /* StackModel.swift */; }; D253BB8A24574CC5002DE544 /* StackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260106423D0CEA700764D80 /* StackModel.swift */; };
D256E9932412880000360572 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = D256E9922412880000360572 /* Header.swift */; }; D256E9932412880000360572 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = D256E9922412880000360572 /* Header.swift */; };
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105223CEA61600764D80 /* ToggleModel.swift */; }; D260105323CEA61600764D80 /* ToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105223CEA61600764D80 /* ToggleModel.swift */; };
@ -557,6 +559,7 @@
94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Regular.otf"; sourceTree = "<group>"; }; 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Regular.otf"; sourceTree = "<group>"; };
94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Bold.otf"; sourceTree = "<group>"; }; 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Bold.otf"; sourceTree = "<group>"; };
94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Regular.otf"; sourceTree = "<group>"; }; 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Regular.otf"; sourceTree = "<group>"; };
94F6516C2437954100631BF9 /* Tabs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = "<group>"; };
AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePayments.swift; sourceTree = "<group>"; }; AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePayments.swift; sourceTree = "<group>"; };
AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = "<group>"; }; AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = "<group>"; };
AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDividerModel.swift; sourceTree = "<group>"; }; AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDividerModel.swift; sourceTree = "<group>"; };
@ -638,6 +641,8 @@
D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.swift; sourceTree = "<group>"; }; D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.swift; sourceTree = "<group>"; };
D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = "<group>"; }; D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = "<group>"; };
D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; }; D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
D253BB9B245874F8002DE544 /* BGImageMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageMolecule.swift; sourceTree = "<group>"; };
D253BB9D2458751F002DE544 /* BGImageMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageMoleculeModel.swift; sourceTree = "<group>"; };
D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = "<group>"; }; D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = "<group>"; };
D260105223CEA61600764D80 /* ToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleModel.swift; sourceTree = "<group>"; }; D260105223CEA61600764D80 /* ToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleModel.swift; sourceTree = "<group>"; };
D260105823D0A92900764D80 /* ContainerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerProtocol.swift; sourceTree = "<group>"; }; D260105823D0A92900764D80 /* ContainerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerProtocol.swift; sourceTree = "<group>"; };
@ -865,10 +870,10 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */, 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */,
D29E28DE23D740FC00ACEA85 /* Container */, D260105823D0A92900764D80 /* ContainerProtocol.swift */,
D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */, D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */,
014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */, 014AA72223C501E2006F3E93 /* ContainerModel.swift */,
D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, D243859823A16B1800332775 /* Container.swift */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1107,6 +1112,7 @@
D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */, D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */,
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */, D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */,
D28A837E23CCA96400DFE4FC /* TabsModel.swift */, D28A837E23CCA96400DFE4FC /* TabsModel.swift */,
94F6516C2437954100631BF9 /* Tabs.swift */,
011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */, 011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */,
017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */, 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */,
); );
@ -1255,6 +1261,22 @@
path = TwoColumn; path = TwoColumn;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D253BB9A24587023002DE544 /* OtherContainers */ = {
isa = PBXGroup;
children = (
D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */,
014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */,
D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */,
D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */,
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */,
012A88C5238DA34000FE3DA1 /* ModuleMoleculeModel.swift */,
D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */,
D253BB9D2458751F002DE544 /* BGImageMoleculeModel.swift */,
D253BB9B245874F8002DE544 /* BGImageMolecule.swift */,
);
path = OtherContainers;
sourceTree = "<group>";
};
D260105723CF9CC500764D80 /* Doughnut */ = { D260105723CF9CC500764D80 /* Doughnut */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1378,6 +1400,7 @@
D29DF10E21E67A77003B2FB9 /* Molecules */ = { D29DF10E21E67A77003B2FB9 /* Molecules */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D253BB9A24587023002DE544 /* OtherContainers */,
D22B38E923F4E07800490EF6 /* DesignedComponents */, D22B38E923F4E07800490EF6 /* DesignedComponents */,
D22479912316A9EF003FCCF9 /* Items */, D22479912316A9EF003FCCF9 /* Items */,
D224798F2316A99F003FCCF9 /* LeftRightViews */, D224798F2316A99F003FCCF9 /* LeftRightViews */,
@ -1389,10 +1412,6 @@
D2A514662213885800345BFB /* MoleculeHeaderView.swift */, D2A514662213885800345BFB /* MoleculeHeaderView.swift */,
012A88EB238F084D00FE3DA1 /* FooterModel.swift */, 012A88EB238F084D00FE3DA1 /* FooterModel.swift */,
D274CA322236A78900B01B62 /* FooterView.swift */, D274CA322236A78900B01B62 /* FooterView.swift */,
012A88C5238DA34000FE3DA1 /* ModuleMoleculeModel.swift */,
D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */,
D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */,
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */,
D260105723CF9CC500764D80 /* Doughnut */, D260105723CF9CC500764D80 /* Doughnut */,
D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */, D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */,
); );
@ -1672,17 +1691,6 @@
path = StringAndMoleculeStack; path = StringAndMoleculeStack;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D29E28DE23D740FC00ACEA85 /* Container */ = {
isa = PBXGroup;
children = (
014AA72223C501E2006F3E93 /* ContainerModel.swift */,
D260105823D0A92900764D80 /* ContainerProtocol.swift */,
D243859823A16B1800332775 /* Container.swift */,
D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */,
);
path = Container;
sourceTree = "<group>";
};
D2B18B7D236090D500A9AEDC /* BaseClasses */ = { D2B18B7D236090D500A9AEDC /* BaseClasses */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1985,6 +1993,7 @@
01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */, 01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */,
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */, 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */,
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
94F6516D2437954100631BF9 /* Tabs.swift in Sources */,
5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */, 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */,
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
D264FA8E243BCD9A00D98315 /* CollectionTemplate.swift in Sources */, D264FA8E243BCD9A00D98315 /* CollectionTemplate.swift in Sources */,
@ -2073,6 +2082,7 @@
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */, AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */,
522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */, 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */,
8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */, 8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */,
D253BB9E2458751F002DE544 /* BGImageMoleculeModel.swift in Sources */,
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */,
8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */, 8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */,
BBAA4F03243D8E3B005AAD5F /* RadioBoxes.swift in Sources */, BBAA4F03243D8E3B005AAD5F /* RadioBoxes.swift in Sources */,
@ -2093,6 +2103,7 @@
D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */, D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */,
0AE14F64238315D2005417F8 /* TextField.swift in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */, 0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */,
D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */, D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */,
AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */, AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */,
C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */,

View File

@ -24,7 +24,7 @@ import UIKit
textField.setContentCompressionResistancePriority(.required, for: .vertical) textField.setContentCompressionResistancePriority(.required, for: .vertical)
textField.setContentCompressionResistancePriority(.required, for: .horizontal) textField.setContentCompressionResistancePriority(.required, for: .horizontal)
textField.textAlignment = .center textField.textAlignment = .center
textField.font = MFStyler.fontForTextField() textField.font = Styler.Font.RegularBodyLarge.getFont()
textField.keyboardType = .numberPad textField.keyboardType = .numberPad
return textField return textField
}() }()
@ -48,11 +48,11 @@ import UIKit
DispatchQueue.main.async { [weak self] in DispatchQueue.main.async { [weak self] in
guard let self = self else { return } guard let self = self else { return }
self.borderStrokeColor = error ? .mfPumpkin() : .mfSilver() self.borderStrokeColor = error ? .mvmOrange : .mvmCoolGray3
let barHeight: CGFloat = self.showError ? 4 : 1 let barHeight: CGFloat = self.showError ? 4 : 1
self.bottomBar?.frame = CGRect(x: 0, y: self.bounds.height - barHeight, width: self.bounds.width, height: barHeight) self.bottomBar?.frame = CGRect(x: 0, y: self.bounds.height - barHeight, width: self.bounds.width, height: barHeight)
self.bottomBar?.backgroundColor = self.showError ? UIColor.mfPumpkin().cgColor : UIColor.black.cgColor self.bottomBar?.backgroundColor = self.showError ? UIColor.mvmOrange.cgColor : UIColor.mvmBlack.cgColor
self.setNeedsDisplay() self.setNeedsDisplay()
self.layoutIfNeeded() self.layoutIfNeeded()
@ -97,29 +97,24 @@ import UIKit
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
guard constraints.isEmpty else { return }
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .clear
addSubview(digitField) addSubview(digitField)
digitField.delegate = self digitField.delegate = self
digitField.didDeleteDelegate = self digitField.didDeleteDelegate = self
NSLayoutConstraint.activate([
digitField.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne),
digitField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: PaddingOne),
bottomAnchor.constraint(equalTo: digitField.bottomAnchor, constant: PaddingOne),
trailingAnchor.constraint(equalTo: digitField.trailingAnchor, constant: PaddingOne),
digitField.centerYAnchor.constraint(equalTo: centerYAnchor),
digitField.centerXAnchor.constraint(equalTo: centerXAnchor)])
widthConstraint = widthAnchor.constraint(equalToConstant: DigitBox.size.width) widthConstraint = widthAnchor.constraint(equalToConstant: DigitBox.size.width)
widthConstraint?.isActive = true widthConstraint?.isActive = true
heightConstraint = heightAnchor.constraint(equalToConstant: DigitBox.size.height) heightConstraint = heightAnchor.constraint(equalToConstant: DigitBox.size.height)
heightConstraint?.isActive = true heightConstraint?.isActive = true
NSLayoutConstraint.activate([
digitField.topAnchor.constraint(equalTo: topAnchor, constant: Padding.Three),
digitField.leadingAnchor.constraint(equalTo: leadingAnchor),
bottomAnchor.constraint(equalTo: digitField.bottomAnchor, constant: Padding.Three),
trailingAnchor.constraint(equalTo: digitField.trailingAnchor),
digitField.centerYAnchor.constraint(equalTo: centerYAnchor)
])
if let bottomBar = bottomBar { if let bottomBar = bottomBar {
layer.addSublayer(bottomBar) layer.addSublayer(bottomBar)
} }
@ -146,7 +141,7 @@ import UIKit
super.reset() super.reset()
backgroundColor = .clear backgroundColor = .clear
digitField.font = MFStyler.fontForTextField() digitField.font = Styler.Font.RegularBodyLarge.getFont()
} }
//-------------------------------------------------- //--------------------------------------------------
@ -186,7 +181,7 @@ import UIKit
sizeObject?.performBlockBase(onSize: size) sizeObject?.performBlockBase(onSize: size)
widthConstraint?.constant = width widthConstraint?.constant = width
heightConstraint?.constant = height heightConstraint?.constant = height
digitField.font = MFFonts.mfFont55Rg(pointSize) digitField.font = MFFonts.mfFontDSRegular(pointSize)
previousSize = size previousSize = size
} }

View File

@ -35,6 +35,7 @@ import UIKit
digitBoxes.append(newDigitBox) digitBoxes.append(newDigitBox)
} }
self.digitBoxes.forEach { $0.removeFromSuperview() }
self.digitBoxes = digitBoxes self.digitBoxes = digitBoxes
guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize() else { return } guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize() else { return }
@ -76,6 +77,10 @@ import UIKit
public var digitBoxes: [DigitBox] = [] public var digitBoxes: [DigitBox] = []
private var selectedDigitBox: DigitBox? private var selectedDigitBox: DigitBox?
public var digitEntryModel: DigitEntryFieldModel? {
return model as? DigitEntryFieldModel
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Computed Properties // MARK: - Computed Properties
//-------------------------------------------------- //--------------------------------------------------
@ -224,14 +229,24 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
@objc open override func updateView(_ size: CGFloat) { @objc open override func updateView(_ size: CGFloat) {
super.updateView(size)
entryFieldContainer.disableAllBorders = true entryFieldContainer.disableAllBorders = true
if !self.digitBoxes.isEmpty { if !self.digitBoxes.isEmpty {
self.digitBoxes.forEach { $0.updateView(size) } self.digitBoxes.forEach { $0.updateView(size) }
} }
layoutIfNeeded()
super.updateView(size)
}
public override func reset() {
super.reset()
accessibilityElements = nil
switchFieldsAutomatically = false
selectedDigitBox = nil
text = ""
digitBoxes.forEach { $0.digitField.text = "" }
} }
//-------------------------------------------------- //--------------------------------------------------
@ -326,7 +341,7 @@ import UIKit
} }
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? DigitEntryFieldModel else { return } guard let model = model as? DigitEntryFieldModel else { return }
numberOfDigits = model.digits numberOfDigits = model.digits
@ -341,7 +356,7 @@ import UIKit
$0.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate, $0.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
action: #selector(observingDelegate.dismissFieldInput)) action: #selector(observingDelegate.dismissFieldInput))
} }
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
} }
@ -378,12 +393,14 @@ extension DigitEntryField {
// One character, switch old value with new, select next textfield // One character, switch old value with new, select next textfield
textField.text = string textField.text = string
digitEntryModel?.text = text
selectNextDigitField(textField, clear: false) selectNextDigitField(textField, clear: false)
return false return false
} else if replacementLength == 0 && oldLength == 1 { } else if replacementLength == 0 && oldLength == 1 {
// Non empty cell, clear and stay. // Non empty cell, clear and stay.
textField.text = "" textField.text = ""
digitEntryModel?.text = text
return false return false
} }
@ -410,6 +427,7 @@ extension DigitEntryField {
if !switchFieldsAutomatically { if !switchFieldsAutomatically {
textField.text = "" textField.text = ""
digitEntryModel?.text = text
} }
proprietorTextDelegate?.textFieldDidBeginEditing?(textField) proprietorTextDelegate?.textFieldDidBeginEditing?(textField)

View File

@ -41,7 +41,7 @@ import UIKit
// MARK: - Delegate // MARK: - Delegate
//-------------------------------------------------- //--------------------------------------------------
weak var delegateObject: MVMCoreUIDelegateObject? var delegateObject: MVMCoreUIDelegateObject?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Stored Properties // MARK: - Stored Properties
@ -60,6 +60,7 @@ import UIKit
self.titleLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3 self.titleLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3
self.feedbackLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3 self.feedbackLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3
self.entryFieldContainer.isEnabled = enabled self.entryFieldContainer.isEnabled = enabled
self.entryFieldModel?.enabled = enabled
} }
} }
@ -69,6 +70,7 @@ import UIKit
set (error) { set (error) {
self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback
self.entryFieldContainer.showError = error self.entryFieldContainer.showError = error
self.entryFieldModel?.showError = error
} }
} }
@ -77,6 +79,7 @@ import UIKit
get { return entryFieldContainer.isLocked } get { return entryFieldContainer.isLocked }
set (locked) { set (locked) {
self.entryFieldContainer.isLocked = locked self.entryFieldContainer.isLocked = locked
self.entryFieldModel?.locked = locked
} }
} }
@ -85,6 +88,7 @@ import UIKit
get { return entryFieldContainer.isSelected } get { return entryFieldContainer.isSelected }
set (selected) { set (selected) {
self.entryFieldContainer.isSelected = selected self.entryFieldContainer.isSelected = selected
self.entryFieldModel?.selected = selected
} }
} }
@ -257,11 +261,13 @@ import UIKit
if let isLocked = model.locked { if let isLocked = model.locked {
self.isLocked = isLocked self.isLocked = isLocked
} else if let isSelected = model.selected { } else if (model.selected ?? false) && !model.wasInitiallySelected {
self.isSelected = isSelected
model.wasInitiallySelected = true
self.isSelected = true
} }
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 115 return 115
} }

View File

@ -10,7 +10,6 @@ import Foundation
@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol { @objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -24,12 +23,14 @@ import Foundation
public var feedback: String? public var feedback: String?
public var errorMessage: String? public var errorMessage: String?
public var enabled: Bool = true public var enabled: Bool = true
public var showError: Bool?
public var locked: Bool? public var locked: Bool?
public var selected: Bool? public var selected: Bool?
public var text: String? public var text: String?
public var fieldKey: String? public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable? public var baseValue: AnyHashable?
public var wasInitiallySelected: Bool = false
public var isValid: Bool? { public var isValid: Bool? {
didSet { updateUI?() } didSet { updateUI?() }
@ -51,6 +52,7 @@ import Foundation
case errorMessage case errorMessage
case locked case locked
case selected case selected
case showError
case text case text
case fieldKey case fieldKey
case groupName case groupName
@ -93,6 +95,7 @@ import Foundation
text = try typeContainer.decodeIfPresent(String.self, forKey: .text) text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
baseValue = text baseValue = text
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName self.groupName = groupName
} }
@ -106,6 +109,7 @@ import Foundation
try container.encodeIfPresent(feedback, forKey: .feedback) try container.encodeIfPresent(feedback, forKey: .feedback)
try container.encodeIfPresent(text, forKey: .text) try container.encodeIfPresent(text, forKey: .text)
try container.encodeIfPresent(locked, forKey: .locked) try container.encodeIfPresent(locked, forKey: .locked)
try container.encodeIfPresent(showError, forKey: .showError)
try container.encodeIfPresent(selected, forKey: .selected) try container.encodeIfPresent(selected, forKey: .selected)
try container.encodeIfPresent(errorMessage, forKey: .errorMessage) try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)

View File

@ -339,6 +339,10 @@ import UIKit
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
setupTextFieldToolbar() setupTextFieldToolbar()
if isSelected {
startEditing()
}
} }
} }

View File

@ -88,6 +88,7 @@ import Foundation
// Horizontal Combination Molecules // Horizontal Combination Molecules
MoleculeObjectMapping.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MoleculeObjectMapping.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Tabs.self, viewModelClass: TabsModel.self)
// Vertical Combination Molecules // Vertical Combination Molecules
MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self) MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self)
@ -125,6 +126,7 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self) MoleculeObjectMapping.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: BGImageMolecule.self, viewModelClass: BGImageMoleculeModel.self)
// Other Molecules // Other Molecules
MoleculeObjectMapping.shared()?.register(viewClass: DoughnutChartView.self, viewModelClass: DoughnutChartModel.self) MoleculeObjectMapping.shared()?.register(viewClass: DoughnutChartView.self, viewModelClass: DoughnutChartModel.self)

View File

@ -0,0 +1,320 @@
//
// Tabs.swift
// MVMCoreUI
//
// Created by Ryan on 2/7/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import UIKit
@objc public protocol TabsDelegate {
func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool
func didSelectItem(_ indexPath: IndexPath, tabs: Tabs)
}
@objcMembers open class Tabs: View, MVMCoreUIViewConstrainingProtocol {
public var tabsModel: TabsModel? {
get { return model as? TabsModel }
}
var delegateObject: MVMCoreUIDelegateObject?
var additionalData: [AnyHashable: Any]?
let layout = UICollectionViewFlowLayout()
public var collectionView: UICollectionView?
let bottomScrollView = UIScrollView(frame: .zero)
let bottomContentView = View()
let bottomLine = View()
var bottomLineLeftConstraint: NSLayoutConstraint?
var bottomLineWidthConstraint: NSLayoutConstraint?
private var widthLabel = Label()
//delegate
weak public var delegate: TabsDelegate?
//control var
public var heightConstraint: NSLayoutConstraint?
public var selectedIndex: Int = 0
public var paddingBeforeFirstTab: Bool = true
//constant
let TabCellId = "TabCell"
public let sectionPadding: CGFloat = 20.0
public let cellSpacing: CGFloat = 34.0
public let cellHeight: CGFloat = 34.0
public let bottomLineHeight: CGFloat = 4.0
public let bottomLineWidth: CGFloat = 32.0
public let tabsHeight: CGFloat = 38.0
public let bottomLineMovingTime: TimeInterval = 0.2
//-------------------------------------------------
// MARK:- Layout Views
//-------------------------------------------------
open override func reset() {
super.reset()
heightConstraint?.constant = tabsHeight
selectedIndex = 0
paddingBeforeFirstTab = true
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
}
open override func setupView() {
super.setupView()
backgroundColor = .white
setupCollectionView()
setupBottomLine()
setupConstraints()
}
func setupCollectionView () {
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = cellSpacing
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.register(TabItemCell.self, forCellWithReuseIdentifier: TabCellId)
collectionView.backgroundColor = .clear
collectionView.showsVerticalScrollIndicator = false
collectionView.showsHorizontalScrollIndicator = false
collectionView.dataSource = self
collectionView.delegate = self
addSubview(collectionView)
self.collectionView = collectionView
}
func setupBottomLine() {
bottomScrollView.translatesAutoresizingMaskIntoConstraints = false
bottomScrollView.delegate = self
addSubview(bottomScrollView)
bottomScrollView.addSubview(bottomContentView)
bottomLine.backgroundColor = .mvmRed
bottomContentView.addSubview(bottomLine)
bringSubviewToFront(bottomScrollView)
}
func setupConstraints() {
//collection view
NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)
//bottom lines
NSLayoutConstraint.constraintPinSubview(bottomScrollView, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true)
bottomScrollView.heightAnchor.constraint(equalToConstant: bottomLineHeight).isActive = true
NSLayoutConstraint.constraintPinSubview(bottomLine, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false)
bottomLine.heightAnchor.constraint(equalToConstant: bottomLineHeight).isActive = true
bottomLineLeftConstraint = bottomLine.leftAnchor.constraint(equalTo: bottomContentView.leftAnchor)
bottomLineLeftConstraint?.isActive = true
bottomLineWidthConstraint = bottomLine.widthAnchor.constraint(equalToConstant: bottomLineWidth)
bottomLineWidthConstraint?.isActive = true
NSLayoutConstraint.constraintPinSubview(toSuperview: bottomContentView)
//height
heightConstraint = heightAnchor.constraint(equalToConstant: tabsHeight)
heightConstraint?.isActive = true
}
//-------------------------------------------------
// MARK:- Control Methods
//-------------------------------------------------
public func pinHeight(_ height: CGFloat) {
heightConstraint?.constant = height
setNeedsLayout()
layoutIfNeeded()
}
public func selectIndex(_ index: Int, animated: Bool) {
guard let _ = collectionView, tabsModel?.tabs.count ?? 0 > 0 else {
selectedIndex = index
return
}
MVMCoreDispatchUtility.performBlock(onMainThread: {
let currentIndex = self.selectedIndex
self.selectedIndex = index
self.deselect(indexPath: IndexPath(row: currentIndex, section: 0))
self.selectItem(atIndexPath: IndexPath(row: index, section: 0), animated: animated)
})
}
public func reloadData() {
collectionView?.reloadData()
}
//-------------------------------------------------
// MARK:- Molecule Setup
//-------------------------------------------------
override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject
self.additionalData = additionalData
self.selectedIndex = tabsModel?.selectedIndex ?? 0
self.bottomLine.backgroundColor = tabsModel?.selectedColor.uiColor
reloadData()
}
}
//-------------------------------------------------
// MARK:- Collection View Methods
//-------------------------------------------------
extension Tabs: UICollectionViewDataSource {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tabsModel?.tabs.count ?? 0
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let labelModel = tabsModel?.tabs[indexPath.row].label, let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TabCellId, for: indexPath) as? TabItemCell else {
return UICollectionViewCell()
}
cell.updateCell(labelModel: labelModel, indexPath: indexPath, delegateObject: delegateObject, additionalData: additionalData, selected: indexPath.row == selectedIndex, tabsModel: tabsModel)
return cell
}
}
extension Tabs: UICollectionViewDelegateFlowLayout {
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
guard let labelModel = tabsModel?.tabs[indexPath.row].label else {
return .zero
}
return CGSize(width: getLabelWidth(labelModel).width, height: cellHeight)
}
//pre calculate the width of the collection cell
//when user select tabs, it will reload related collectionview, if we use autosize, it would relayout the width, need to keep the cell width constant.
func getLabelWidth(_ labelModel: LabelModel?) -> CGSize {
guard let labelModel = labelModel else { return .zero}
widthLabel.set(with: labelModel, nil, nil)
let cgSize = widthLabel.intrinsicContentSize
widthLabel.reset()
return cgSize
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
if !paddingBeforeFirstTab && section == 0 {
return .zero
} else {
return UIEdgeInsets(top: 0, left: sectionPadding, bottom: 0, right: 0)
}
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return sectionPadding
}
public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
return delegate?.shouldSelectItem(indexPath, tabs: self) ?? true
}
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectIndex(indexPath.row, animated: true)
}
public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard let tabCell = cell as? TabItemCell else { return }
if indexPath.row == selectedIndex {
moveBottomLine(toIndex: indexPath, animated: false, cell: tabCell)
}
}
func deselect(indexPath:IndexPath) {
collectionView?.deselectItem(at: indexPath, animated: false)
collectionView?.reloadItems(at: [indexPath])
}
func selectItem(atIndexPath indexPath: IndexPath, animated: Bool) {
guard let collect = collectionView, tabsModel?.tabs.count ?? 0 > 0 else { return }
collect.selectItem(at: indexPath, animated: animated, scrollPosition: .centeredHorizontally)
guard let tabCell = collect.cellForItem(at: indexPath) as? TabItemCell, let tabsModel = self.tabsModel else { return }
self.moveBottomLine(toIndex: indexPath, animated: animated, cell: tabCell)
tabCell.label.textColor = tabsModel.selectedColor.uiColor
tabCell.updateAccessibility(indexPath: indexPath, selected: true, tabsModel: tabsModel)
tabCell.setNeedsDisplay()
tabCell.setNeedsLayout()
tabCell.layoutIfNeeded()
self.delegate?.didSelectItem(indexPath, tabs: self)
}
}
extension Tabs: UIScrollViewDelegate {
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
/*bottomScrollview is subview of self, it's not belongs to collectionview.
When collectionview is scrolling, bottomScrollView will stay without moving
Adding collectionview's offset to bottomScrollView, will make the bottomScrollview looks like scrolling with the selected tab item.
*/
guard let offsetX = collectionView?.contentOffset.x else { return }
bottomScrollView.setContentOffset(CGPoint(x: offsetX, y: bottomScrollView.contentOffset.y), animated: false)
}
}
//-------------------------------------------------
// MARK:- Bottom Line Methods
//-------------------------------------------------
extension Tabs {
func moveBottomLine(toIndex indexPath: IndexPath, animated: Bool, cell: TabItemCell) {
guard let collect = self.collectionView else {return}
let size = collectionView(collect, layout: layout, sizeForItemAt: indexPath)
let barWidth = max(size.width, bottomLineWidth)
let animationBlock = {
[weak self] in
let x = cell.frame.origin.x
self?.bottomLineWidthConstraint?.constant = barWidth
self?.bottomLineLeftConstraint?.constant = x + (size.width - barWidth) / 2.0
self?.bottomContentView.layoutIfNeeded()
}
if animated {
UIView.animate(withDuration: bottomLineMovingTime, animations: animationBlock)
} else {
animationBlock()
}
}
}
@objcMembers public class TabItemCell: CollectionViewCell {
public let label = Label()
public var labelModel: LabelModel?
public override func setupView() {
super.setupView()
contentView.addSubview(label)
NSLayoutConstraint.constraintPinSubview(label, pinTop: false, pinBottom: false, pinLeft: true, pinRight: true)
label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
label.baselineAdjustment = .alignCenters
}
public func updateCell(labelModel: LabelModel, indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, selected: Bool, tabsModel: TabsModel?) {
label.reset()
label.set(with: labelModel, delegateObject, additionalData)
self.labelModel = labelModel
if selected, let selectedColor = tabsModel?.selectedColor {
label.textColor = selectedColor.uiColor
}
updateAccessibility(indexPath: indexPath, selected: selected, tabsModel: tabsModel)
}
public func updateAccessibility(indexPath: IndexPath, selected: Bool, tabsModel: TabsModel?) {
//Accessibility
isAccessibilityElement = false
contentView.isAccessibilityElement = true
let accKey = selected ? "toptabbar_tab_selected" : "AccTab"
let accLabel = "\(label.text ?? "") \(MVMCoreUIUtility.hardcodedString(withKey: accKey) ?? "")"
let accOrder = String(format: MVMCoreUIUtility.hardcodedString(withKey: "AccTabIndex") ?? "", indexPath.row + 1, tabsModel?.tabs.count ?? 0)
contentView.accessibilityLabel = "\(accLabel) \(accOrder)"
contentView.accessibilityHint = selected ? nil : MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint")
}
}

View File

@ -11,7 +11,7 @@ import UIKit
public class TabsModel: MoleculeModelProtocol { public class TabsModel: MoleculeModelProtocol {
public static var identifier: String = "tabs" public static var identifier: String = "tabs"
public var backgroundColor: Color? public var backgroundColor: Color?
public var tabs: [LabelModel] public var tabs: [TabItemModel]
public var selectedColor = Color(uiColor: .mfTomatoRed()) public var selectedColor = Color(uiColor: .mfTomatoRed())
// Must be capped to 0...(tabs.count - 1) // Must be capped to 0...(tabs.count - 1)
@ -25,13 +25,13 @@ public class TabsModel: MoleculeModelProtocol {
case moleculeName case moleculeName
} }
public init(with tabs: [LabelModel]) { public init(with tabs: [TabItemModel]) {
self.tabs = tabs self.tabs = tabs
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
tabs = try typeContainer.decode([LabelModel].self, forKey: .tabs) tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) { if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) {
selectedColor = color selectedColor = color
@ -50,3 +50,33 @@ public class TabsModel: MoleculeModelProtocol {
try container.encode(selectedIndex, forKey: .selectedIndex) try container.encode(selectedIndex, forKey: .selectedIndex)
} }
} }
public class TabItemModel: Codable {
var label: LabelModel
var action: ActionModelProtocol?
init(label: LabelModel) {
self.label = label
}
private enum CodingKeys: String, CodingKey {
case label
case action
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
label = try typeContainer.decode(LabelModel.self, forKey: .label)
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeModel(label, forKey: .label)
try container.encodeModelIfPresent(action, forKey: .action)
}
}

View File

@ -45,8 +45,11 @@ import Foundation
if useVerticalMargins == nil { if useVerticalMargins == nil {
useVerticalMargins = true useVerticalMargins = true
} }
if style == nil { if topPadding == nil {
style = "standard" topPadding = 24
}
if bottomPadding == nil {
bottomPadding = 24
} }
} }

View File

@ -9,10 +9,10 @@
import UIKit import UIKit
@objcMembers public class TabsTableViewCell: TableViewCell { @objcMembers public class TabsTableViewCell: TableViewCell {
/*var tabsListItemModel: TabsListItemModel? { var tabsListItemModel: TabsListItemModel? {
return listItemModel as? TabsListItemModel return listItemModel as? TabsListItemModel
} }
let tabs = TopTabbar(frame: .zero) let tabs = Tabs(frame: .zero)
var delegateObject: MVMCoreUIDelegateObject? var delegateObject: MVMCoreUIDelegateObject?
var previousTabIndex = 0 var previousTabIndex = 0
@ -22,7 +22,6 @@ import UIKit
tabs.paddingBeforeFirstTab = false tabs.paddingBeforeFirstTab = false
tabs.translatesAutoresizingMaskIntoConstraints = false tabs.translatesAutoresizingMaskIntoConstraints = false
tabs.delegate = self tabs.delegate = self
tabs.datasource = self
contentView.addSubview(tabs) contentView.addSubview(tabs)
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: tabs, useMargins: true).values)) NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: tabs, useMargins: true).values))
@ -39,7 +38,9 @@ import UIKit
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject self.delegateObject = delegateObject
tabs.reloadData() if let tabsModel = tabsListItemModel?.tabs {
tabs.set(with: tabsModel, delegateObject, additionalData)
}
} }
public override func reset() { public override func reset() {
@ -53,33 +54,22 @@ import UIKit
} }
} }
extension TabsTableViewCell: TopTabbarDelegate { extension TabsTableViewCell: TabsDelegate {
public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool { public func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool {
if let model = tabsListItemModel { if let model = tabsListItemModel {
let molecules = model.molecules[topTabbar.selectedIndex] let molecules = model.molecules[tabs.selectedIndex]
delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: index < tabs.selectedIndex ? .right : .left) delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: indexPath.row < tabs.selectedIndex ? .right : .left)
} }
previousTabIndex = tabs.selectedIndex previousTabIndex = tabs.selectedIndex
return true return true
} }
public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) { public func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) {
guard let model = tabsListItemModel, let index = indexPath.row
let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) else { return } if let model = tabsListItemModel, index < model.molecules.count {
let molecules = model.molecules[index] let molecules = model.molecules[index]
delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right) delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right)
}
}
extension TabsTableViewCell: TopTabbarDataSource {
public func number(ofTopTabbarItems topTabbar: TopTabbar) -> Int {
return tabsListItemModel?.tabs.tabs.count ?? 0
}
public func topTabbar(_ topTabbar: TopTabbar, titleForItemAt index: Int) -> String? {
guard let title = tabsListItemModel?.tabs.tabs[index].text else {
return "Select"
} }
return title }
}*/
} }

View File

@ -0,0 +1,25 @@
//
// BGImageMolecule.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 4/28/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class BGImageMolecule: MoleculeContainer {
let image = MFLoadImageView(pinnedEdges: .all)
open override func setupView() {
super.setupView()
insertSubview(image, at: 0)
NSLayoutConstraint.constraintPinSubview(toSuperview: image)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
image.setOptional(with: (model as? BGImageMoleculeModel)?.image, delegateObject, additionalData)
super.set(with: model, delegateObject, additionalData)
}
}

View File

@ -0,0 +1,52 @@
//
// BGImageMoleculeModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 4/28/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class BGImageMoleculeModel: MoleculeContainerModel {
public override class var identifier: String {
return "bgImageContainer"
}
public var image: ImageViewModel
open override func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topPadding == nil {
topPadding = PaddingDefaultVerticalSpacing3
}
if bottomPadding == nil {
bottomPadding = PaddingDefaultVerticalSpacing3
}
}
private enum CodingKeys: String, CodingKey {
case image
}
public init(_ image: ImageViewModel, molecule: MoleculeModelProtocol) {
self.image = image
super.init(with: molecule)
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
image = try typeContainer.decode(ImageViewModel.self, forKey:.image)
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.encode(image, forKey: .image)
}
}

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
public class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol, MoleculeModelProtocol { open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol, MoleculeModelProtocol {
public class var identifier: String { public class var identifier: String {
return "container" return "container"
} }

View File

@ -148,6 +148,7 @@ import UIKit
preservesSuperviewLayoutMargins = false preservesSuperviewLayoutMargins = false
contentView.insetsLayoutMarginsFromSafeArea = false contentView.insetsLayoutMarginsFromSafeArea = false
contentView.preservesSuperviewLayoutMargins = false contentView.preservesSuperviewLayoutMargins = false
styleStandard()
} }
//TODO: ModelProtocol, Change to model //TODO: ModelProtocol, Change to model
@ -183,6 +184,7 @@ import UIKit
open func reset() { open func reset() {
molecule?.reset() molecule?.reset()
styleStandard()
backgroundColor = .white backgroundColor = .white
} }

View File

@ -301,11 +301,12 @@
[weakSelf.viewToLayout layoutIfNeeded]; [weakSelf.viewToLayout layoutIfNeeded];
}; };
//accessibility - added to make only top alert label and close button accessible. Posted notification when top alert is displayed
weakSelf.accessibilityElements = @[weakSelf.buttonView];
weakSelf.shortView.isAccessibilityElement = NO;
weakSelf.buttonView.label.accessibilityLabel = [NSString stringWithFormat:@"%@ - %@", [MVMCoreUIUtility hardcodedStringWithKey:@"top_alert_notification"],weakSelf.buttonView.label.accessibilityLabel];
void(^completion)(void) = ^(void) { void(^completion)(void) = ^(void) {
//accessibility - added to make only top alert label and close button accessible. Posted notification when top alert is displayed
weakSelf.accessibilityElements = @[weakSelf.buttonView];
weakSelf.shortView.isAccessibilityElement = NO;
weakSelf.buttonView.label.accessibilityLabel = [NSString stringWithFormat:@"%@ - %@", [MVMCoreUIUtility hardcodedStringWithKey:@"top_alert_notification"],weakSelf.buttonView.label.accessibilityLabel];
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, weakSelf.buttonView.label); UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, weakSelf.buttonView.label);
[operation markAsFinished]; [operation markAsFinished];
}; };