From c5664d80e4eea93e8bd80ee89d44c632d6694743 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 1 Jun 2020 17:20:17 -0400 Subject: [PATCH] Tabs update --- MVMCoreUI.xcodeproj/project.pbxproj | 4 +++ .../ModelProtocols/TabPageModelProtocol.swift | 14 ++++++++++ .../Atomic/Templates/TemplateModel.swift | 13 +++++++++- .../BaseControllers/ViewController.swift | 22 +++++++++++----- .../MVMCoreUISplitViewController.h | 5 +++- .../MVMCoreUISplitViewController.m | 26 ++++++++++++------- 6 files changed, 66 insertions(+), 18 deletions(-) create mode 100644 MVMCoreUI/Atomic/Protocols/ModelProtocols/TabPageModelProtocol.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index ba6f08bd..331da73c 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -334,6 +334,7 @@ D28BA741248025A300B75CB8 /* TabBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28BA740248025A300B75CB8 /* TabBarModel.swift */; }; D28BA7432480284E00B75CB8 /* TabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28BA7422480284E00B75CB8 /* TabBar.swift */; }; D28BA7452481652D00B75CB8 /* TabBarProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28BA7442481652D00B75CB8 /* TabBarProtocol.swift */; }; + D28BA74D248589C800B75CB8 /* TabPageModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28BA74C248589C800B75CB8 /* TabPageModelProtocol.swift */; }; D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */; }; D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29C94D4242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift */; }; @@ -768,6 +769,7 @@ D28BA740248025A300B75CB8 /* TabBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarModel.swift; sourceTree = ""; }; D28BA7422480284E00B75CB8 /* TabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBar.swift; sourceTree = ""; }; D28BA7442481652D00B75CB8 /* TabBarProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarProtocol.swift; sourceTree = ""; }; + D28BA74C248589C800B75CB8 /* TabPageModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabPageModelProtocol.swift; sourceTree = ""; }; D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewConstrainingProtocol.h; sourceTree = ""; }; D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModuleMolecule.swift; sourceTree = ""; }; D29C94D4242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUICommonViewsUtility+Extension.swift"; sourceTree = ""; }; @@ -904,6 +906,7 @@ D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */, D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */, D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */, + D28BA74C248589C800B75CB8 /* TabPageModelProtocol.swift */, ); path = ModelProtocols; sourceTree = ""; @@ -2100,6 +2103,7 @@ BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */, D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */, + D28BA74D248589C800B75CB8 /* TabPageModelProtocol.swift in Sources */, 014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */, 0A21DB91235E0EDB00C160A2 /* DigitBox.swift in Sources */, BBAA4F04243D8E3B005AAD5F /* RadioBoxModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/TabPageModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TabPageModelProtocol.swift new file mode 100644 index 00000000..dbee61bd --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/TabPageModelProtocol.swift @@ -0,0 +1,14 @@ +// +// TabPageModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 6/1/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol TabPageModelProtocol { + var tabBarHidden: Bool { get set } + var tabBarIndex: Int? { get set } +} diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/TemplateModel.swift index b478167d..01753414 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/TemplateModel.swift @@ -9,7 +9,7 @@ import Foundation -@objcMembers public class TemplateModel: MVMControllerModelProtocol { +@objcMembers public class TemplateModel: MVMControllerModelProtocol, TabPageModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -29,6 +29,9 @@ import Foundation public var navigationBar: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var formRules: [FormGroupRule]? public var behaviors: [PageBehaviorProtocol]? + + public var tabBarHidden: Bool = false + public var tabBarIndex: Int? //-------------------------------------------------- // MARK: - Initializer @@ -50,6 +53,8 @@ import Foundation case formRules case behaviors case navigationBar + case tabBarHidden + case tabBarIndex } //-------------------------------------------------- @@ -64,6 +69,10 @@ import Foundation formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules) behaviors = try typeContainer.decodeModelsIfPresent(codingKey: .behaviors) navigationBar = try typeContainer.decodeModelIfPresent(codingKey: .navigationBar) + if let tabBarHidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .tabBarHidden) { + self.tabBarHidden = tabBarHidden + } + tabBarIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .tabBarIndex) } public func encode(to encoder: Encoder) throws { @@ -74,5 +83,7 @@ import Foundation try container.encodeIfPresent(screenHeading, forKey: .screenHeading) try container.encodeIfPresent(formRules, forKey: .formRules) try container.encodeModelIfPresent(navigationBar, forKey: .navigationBar) + try container.encode(tabBarHidden, forKey: .tabBarHidden) + try container.encodeIfPresent(tabBarIndex, forKey: .tabBarIndex) } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 51fc1b56..717a5761 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -259,6 +259,16 @@ import UIKit MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(progress / Float(100)) } } + + // MARK: - TabBar + open func updateTabBar() { + guard MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() == self, + var tabModel = pageModel as? TabPageModelProtocol else { return } + if let index = tabModel.tabBarIndex { + MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index) + } + MVMCoreUISplitViewController.main()?.updateTabBarShowing(!tabModel.tabBarHidden) + } // MARK: - View lifecycle @@ -314,11 +324,6 @@ import UIKit open override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - // Select tab if needed. - if let tab: Int = loadObject?.pageJSON?["tabBarIndex"] as? Int { - MVMCoreUISplitViewController.main()?.tabBar.highlightTab(at: tab) - } - // Update the navigation bar ui when view is appearing. Can remove check in the future, see viewControllerReady if manager == nil { setNavigationController() @@ -328,6 +333,9 @@ import UIKit open override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + // Update tab if needed. + updateTabBar() + if manager == nil { MVMCoreUISession.sharedGlobal()?.currentPageType = pageType MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) @@ -377,7 +385,7 @@ import UIKit } // MARK: - MVMCoreLoadDelegateProtocol - // TODO: Move this function out of here after breaking down load operation into smaller tasks and remove protocol from base. + // TODO: Move this function out of here after architecture cleanup. open func loadFinished(_ loadObject: MVMCoreLoadObject?, loadedViewController: (UIViewController & MVMCoreViewControllerProtocol)?, error: MVMCoreErrorObject?) { MVMCoreUILoggingHandler.log(withDelegateLoadFinished: loadObject, loadedViewController: loadedViewController, error: error) @@ -393,7 +401,7 @@ import UIKit error == nil, loadObject?.pageJSON?["tabBarIndex"] == nil { MVMCoreDispatchUtility.performBlock(onMainThread: { - MVMCoreUISplitViewController.main()?.tabBar.highlightTab(at: tab) + MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: tab) }) } } diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h index ca06471d..4d6b2cff 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h @@ -50,7 +50,7 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) { @property (nullable, weak, nonatomic, readonly) UIViewController *navigationItemViewController; /// Reference to the tabbar. -@property (weak, nonatomic) UIView *tabBar; +@property (nullable, weak, nonatomic) UIView *tabBar; // Convenience getter + (nullable instancetype)mainSplitViewController; @@ -154,4 +154,7 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) { /// Adds any tabbar at the bottom of the split view. - (void)addTabBar:(nonnull UIView *)tabBar; +/// Updates if the tab bar is showing or not. +- (void)updateTabBarShowing:(BOOL)showing; + @end diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index b46bb184..149000c0 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -781,16 +781,26 @@ CGFloat const PanelAnimationDuration = 0.2; - (void)addTabBar:(nonnull UIView *)tabBar { [self.view insertSubview:tabBar atIndex:0]; + self.tabBar = tabBar; [tabBar.topAnchor constraintEqualToAnchor:self.mainView.bottomAnchor].active = YES; [NSLayoutConstraint constraintWithItem:tabBar attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.mainView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0].active = YES; [NSLayoutConstraint constraintWithItem:tabBar attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.mainView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0].active = YES; - + [self updateTabBarShowing:YES]; +} + +- (void)updateTabBarShowing:(BOOL)showing { + self.tabBar.hidden = !showing; self.bottomConstraint.active = NO; - NSLayoutConstraint *bottom = [self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:tabBar.bottomAnchor]; - bottom.active = YES; - self.bottomConstraint = bottom; - - self.tabBar = tabBar; + if (showing && self.tabBar) { + NSLayoutConstraint *bottom = [self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:self.tabBar.bottomAnchor]; + bottom.active = YES; + self.bottomConstraint = bottom; + } else { + NSLayoutConstraint *bottom = [self.view.bottomAnchor constraintEqualToAnchor:self.bottomProgressBar.bottomAnchor]; + bottom.active = YES; + self.bottomConstraint = bottom; + } + [self.view layoutIfNeeded]; } #pragma mark - Bottom Progress Bar @@ -873,9 +883,7 @@ CGFloat const PanelAnimationDuration = 0.2; if (tabs) { [self addTabBar:tabs]; } else { - NSLayoutConstraint *bottom = [self.view.bottomAnchor constraintEqualToAnchor:progressView.bottomAnchor]; - bottom.active = YES; - self.bottomConstraint = bottom; + [self updateTabBarShowing:NO]; } // Cover View