merge
This commit is contained in:
commit
6b1d065263
@ -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 */,
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -339,6 +339,10 @@ import UIKit
|
|||||||
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
|
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
|
||||||
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
|
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
|
||||||
setupTextFieldToolbar()
|
setupTextFieldToolbar()
|
||||||
|
|
||||||
|
if isSelected {
|
||||||
|
startEditing()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
320
MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift
Normal file
320
MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
}
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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"
|
||||||
}
|
}
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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];
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user