From 8a33c0c3301f8396d73fe8dc5849c703a41a42c0 Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Thu, 8 Feb 2018 14:11:52 -0600 Subject: [PATCH 1/9] Allow a global customization of the content's drop shadow. Issue #61 --- InteractiveSideMenu.xcodeproj/project.pbxproj | 12 +- Sample/Sample/HostViewController.swift | 10 +- .../Sample/NavigationMenuViewController.swift | 5 +- Sources/MenuAnimator.swift | 58 +++++---- Sources/MenuContainerViewController.swift | 113 +++++++++++------- Sources/MenuTransitioningDelegate.swift | 6 + ...roller.swift => SideMenuItemContent.swift} | 0 Sources/SideMenuItemShadow.swift | 18 +++ 8 files changed, 134 insertions(+), 88 deletions(-) rename Sources/{MenuItemContentViewController.swift => SideMenuItemContent.swift} (100%) create mode 100644 Sources/SideMenuItemShadow.swift diff --git a/InteractiveSideMenu.xcodeproj/project.pbxproj b/InteractiveSideMenu.xcodeproj/project.pbxproj index 12327eb..1941736 100644 --- a/InteractiveSideMenu.xcodeproj/project.pbxproj +++ b/InteractiveSideMenu.xcodeproj/project.pbxproj @@ -12,8 +12,9 @@ 881EF0921E3101130035DEB4 /* InteractiveSideMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 881EF0901E3101130035DEB4 /* InteractiveSideMenu.h */; settings = {ATTRIBUTES = (Public, ); }; }; 881EF0971E3101B80035DEB4 /* MenuAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881EF0931E3101B80035DEB4 /* MenuAnimator.swift */; }; 881EF0981E3101B80035DEB4 /* MenuContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881EF0941E3101B80035DEB4 /* MenuContainerViewController.swift */; }; - 881EF0991E3101B80035DEB4 /* MenuItemContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881EF0951E3101B80035DEB4 /* MenuItemContentViewController.swift */; }; + 881EF0991E3101B80035DEB4 /* SideMenuItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881EF0951E3101B80035DEB4 /* SideMenuItemContent.swift */; }; 881EF09A1E3101B80035DEB4 /* MenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881EF0961E3101B80035DEB4 /* MenuViewController.swift */; }; + D48B8AEC202CDE1A0010D9A4 /* SideMenuItemShadow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48B8AEB202CDE1A0010D9A4 /* SideMenuItemShadow.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -24,8 +25,9 @@ 881EF0901E3101130035DEB4 /* InteractiveSideMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteractiveSideMenu.h; sourceTree = ""; }; 881EF0931E3101B80035DEB4 /* MenuAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuAnimator.swift; sourceTree = ""; }; 881EF0941E3101B80035DEB4 /* MenuContainerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuContainerViewController.swift; sourceTree = ""; }; - 881EF0951E3101B80035DEB4 /* MenuItemContentViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuItemContentViewController.swift; sourceTree = ""; }; + 881EF0951E3101B80035DEB4 /* SideMenuItemContent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideMenuItemContent.swift; sourceTree = ""; }; 881EF0961E3101B80035DEB4 /* MenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuViewController.swift; sourceTree = ""; }; + D48B8AEB202CDE1A0010D9A4 /* SideMenuItemShadow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuItemShadow.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,7 +64,8 @@ 84E2E6761F15406600E5FF37 /* MenuTransitioningDelegate.swift */, 881EF0931E3101B80035DEB4 /* MenuAnimator.swift */, 881EF0941E3101B80035DEB4 /* MenuContainerViewController.swift */, - 881EF0951E3101B80035DEB4 /* MenuItemContentViewController.swift */, + 881EF0951E3101B80035DEB4 /* SideMenuItemContent.swift */, + D48B8AEB202CDE1A0010D9A4 /* SideMenuItemShadow.swift */, 881EF0961E3101B80035DEB4 /* MenuViewController.swift */, 881EF08F1E3101130035DEB4 /* Info.plist */, 881EF0901E3101130035DEB4 /* InteractiveSideMenu.h */, @@ -153,7 +156,8 @@ 881EF0971E3101B80035DEB4 /* MenuAnimator.swift in Sources */, 84E2E6771F15406600E5FF37 /* MenuTransitioningDelegate.swift in Sources */, 881EF0981E3101B80035DEB4 /* MenuContainerViewController.swift in Sources */, - 881EF0991E3101B80035DEB4 /* MenuItemContentViewController.swift in Sources */, + 881EF0991E3101B80035DEB4 /* SideMenuItemContent.swift in Sources */, + D48B8AEC202CDE1A0010D9A4 /* SideMenuItemShadow.swift in Sources */, 84E2E6751F15401000E5FF37 /* Options.swift in Sources */, 881EF09A1E3101B80035DEB4 /* MenuViewController.swift in Sources */, ); diff --git a/Sample/Sample/HostViewController.swift b/Sample/Sample/HostViewController.swift index 1226bc9..779ab81 100644 --- a/Sample/Sample/HostViewController.swift +++ b/Sample/Sample/HostViewController.swift @@ -19,7 +19,7 @@ import UIKit import InteractiveSideMenu -/* +/** HostViewController is container view controller, contains menu controller and the list of relevant view controllers. Responsible for creating and selecting menu items content controlers. @@ -54,9 +54,7 @@ class HostViewController: MenuContainerViewController { override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) - /* - Options to customize menu transition animation. - */ + // Options to customize menu transition animation. var options = TransitionOptions() // Animation duration @@ -71,9 +69,7 @@ class HostViewController: MenuContainerViewController { let controllersIdentifiers = ["Kitty", "TabBar"] var contentList = [UIViewController]() - /* - Instantiate items controllers from storyboard. - */ + // Instantiate items controllers from storyboard. for identifier in controllersIdentifiers { if let viewController = self.storyboard?.instantiateViewController(withIdentifier: identifier) { contentList.append(viewController) diff --git a/Sample/Sample/NavigationMenuViewController.swift b/Sample/Sample/NavigationMenuViewController.swift index bb58a54..f547bc6 100644 --- a/Sample/Sample/NavigationMenuViewController.swift +++ b/Sample/Sample/NavigationMenuViewController.swift @@ -19,7 +19,7 @@ import UIKit import InteractiveSideMenu -/* +/** Menu controller is responsible for creating its content and showing/hiding menu using 'menuContainerViewController' property. */ class NavigationMenuViewController: MenuViewController { @@ -41,9 +41,6 @@ class NavigationMenuViewController: MenuViewController { } } -/* - Extention of `NavigationMenuViewController` class, implements table view delegates methods. - */ extension NavigationMenuViewController: UITableViewDelegate, UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { diff --git a/Sources/MenuAnimator.swift b/Sources/MenuAnimator.swift index 2059fed..4cecd4f 100644 --- a/Sources/MenuAnimator.swift +++ b/Sources/MenuAnimator.swift @@ -25,10 +25,9 @@ final class MenuInteractiveTransition: NSObject { typealias Action = () -> () - //MARK: - Properties - // var present = false var interactionInProgress = false + var shadowOptions: SideMenuItemShadow var options = TransitionOptions() fileprivate let presentAction: Action @@ -42,15 +41,25 @@ final class MenuInteractiveTransition: NSObject { fileprivate var tapRecognizer: UITapGestureRecognizer? fileprivate var panRecognizer: UIPanGestureRecognizer? - required init(presentAction: @escaping Action, dismissAction: @escaping Action) { + required init(shadowOptions: SideMenuItemShadow, presentAction: @escaping Action, dismissAction: @escaping Action) { + self.shadowOptions = shadowOptions self.presentAction = presentAction self.dismissAction = dismissAction super.init() } + + @objc func handlePanPresentation(recognizer: UIPanGestureRecognizer) { + present = true + handlePan(recognizer: recognizer) + } + + @objc func handlePanDismission(recognizer: UIPanGestureRecognizer) { + present = false + handlePan(recognizer: recognizer) + } } //MARK: - UIViewControllerInteractiveTransitioning -// extension MenuInteractiveTransition: UIViewControllerInteractiveTransitioning { func startInteractiveTransition(_ transitionContext: UIViewControllerContextTransitioning) { @@ -59,7 +68,6 @@ extension MenuInteractiveTransition: UIViewControllerInteractiveTransitioning { } //MARK: - UIViewControllerAnimatedTransitioning -// extension MenuInteractiveTransition: UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { @@ -73,22 +81,8 @@ extension MenuInteractiveTransition: UIViewControllerAnimatedTransitioning { } //MARK: - Private methods -// -extension MenuInteractiveTransition { - - @objc func handlePanPresentation(recognizer: UIPanGestureRecognizer) { - present = true - - handlePan(recognizer: recognizer) - } - - @objc func handlePanDismission(recognizer: UIPanGestureRecognizer) { - present = false - - handlePan(recognizer: recognizer) - } - - fileprivate func startTransition(transitionContext: UIViewControllerContextTransitioning) { +private extension MenuInteractiveTransition { + func startTransition(transitionContext: UIViewControllerContextTransitioning) { transitionStarted = true self.transitionContext = transitionContext @@ -141,7 +135,7 @@ extension MenuInteractiveTransition { fromViewController.view.isUserInteractionEnabled = false } - fileprivate func finishTransition(currentPercentComplete : CGFloat) { + func finishTransition(currentPercentComplete : CGFloat) { transitionStarted = false let animation: () -> Void = { [unowned self] in self.updateTransition(percentComplete: 1.0) } @@ -199,7 +193,7 @@ extension MenuInteractiveTransition { } } - private func createSnapshotView(from: UIView) -> UIView { + func createSnapshotView(from: UIView) -> UIView { guard let snapshotView = from.snapshotView(afterScreenUpdates: true) else { print("Invalid snapshot view. Default color will be used") let placeholderView = UIView(frame: from.frame) @@ -211,17 +205,19 @@ extension MenuInteractiveTransition { return snapshotView } - private func addShadow(to view: UIView) { - view.layer.shadowColor = UIColor.black.cgColor - view.layer.shadowOpacity = 0.3 - view.layer.shadowOffset = CGSize(width: -5, height: 5) + func addShadow(to view: UIView) { + view.layer.shadowColor = shadowOptions.color?.cgColor + view.layer.shadowOpacity = Float(shadowOptions.opacity) + view.layer.shadowOffset = shadowOptions.offset } - private func removeShadow(from view: UIView) { + func removeShadow(from view: UIView) { + view.layer.shadowColor = nil + view.layer.shadowOpacity = 0.0 view.layer.shadowOffset = .zero } - private func cancelTransition(currentPercentComplete : CGFloat) { + func cancelTransition(currentPercentComplete : CGFloat) { transitionStarted = false let animation : () -> Void = { [unowned self] in self.updateTransition(percentComplete: 0) } @@ -270,7 +266,7 @@ extension MenuInteractiveTransition { } } - private func handlePan(recognizer: UIPanGestureRecognizer) { + func handlePan(recognizer: UIPanGestureRecognizer) { guard let recognizerView = recognizer.view else { fatalError("Invalid recognizer view value") } @@ -340,7 +336,7 @@ extension MenuInteractiveTransition { } } - private func updateTransition(percentComplete: CGFloat) { + func updateTransition(percentComplete: CGFloat) { guard let transitionContext = self.transitionContext else { fatalError("Invalid `transitionContext` value. This property should not be nil") } diff --git a/Sources/MenuContainerViewController.swift b/Sources/MenuContainerViewController.swift index b7b221b..0316a27 100644 --- a/Sources/MenuContainerViewController.swift +++ b/Sources/MenuContainerViewController.swift @@ -23,8 +23,19 @@ import UIKit */ open class MenuContainerViewController: UIViewController { - // Describes if side menu is shown or not. - var isShown = false + fileprivate weak var currentContentViewController: UIViewController? + fileprivate var navigationMenuTransitionDelegate: MenuTransitioningDelegate! + + /** + Flag indicating if the side menu is being shown. + */ + fileprivate var isShown = false + + public var shadowOptions = SideMenuItemShadow() { + didSet { + navigationMenuTransitionDelegate?.shadowOptions = shadowOptions + } + } /** The view controller for side menu. @@ -58,51 +69,23 @@ open class MenuContainerViewController: UIViewController { */ public var contentViewControllers = [UIViewController]() - /** - Shows left side menu. - */ - public func showSideMenu() { - presentNavigationMenu() - } - - /** - Hides left side menu. - Controller from the right side will be visible. - */ - public func hideSideMenu() { - dismissNavigationMenu() - } - - /** - Embeds menu item content view controller. - - - parameter selectedContentVC: The view controller to be embedded. - */ - public func selectContentViewController(_ selectedContentVC: UIViewController) { - if let currentContentVC = currentContentViewController { - if currentContentVC != selectedContentVC { - currentContentVC.view.removeFromSuperview() - currentContentVC.removeFromParentViewController() - setCurrentView(selectedContentVC) - } - } else { - setCurrentView(selectedContentVC) - } - } // MARK: - Controller lifecycle // override open func viewDidLoad() { super.viewDidLoad() - navigationMenuTransitionDelegate = MenuTransitioningDelegate(interactiveTransition: MenuInteractiveTransition( + let interactiveTransition = MenuInteractiveTransition( + shadowOptions: shadowOptions, presentAction: { [unowned self] in self.presentNavigationMenu() }, dismissAction: { [unowned self] in self.dismissNavigationMenu() } - )) + ) + + navigationMenuTransitionDelegate = MenuTransitioningDelegate(interactiveTransition: interactiveTransition) let screenEdgePanRecognizer = UIScreenEdgePanGestureRecognizer( target: navigationMenuTransitionDelegate.interactiveTransition, @@ -131,18 +114,53 @@ open class MenuContainerViewController: UIViewController { } }, completion: nil) } +} - // MARK: - Private - // - private weak var currentContentViewController: UIViewController? - private var navigationMenuTransitionDelegate: MenuTransitioningDelegate! +// MARK: - Public +extension MenuContainerViewController { + + /** + Shows left side menu. + */ + public func showSideMenu() { + presentNavigationMenu() + } + + /** + Hides left side menu. + Controller from the right side will be visible. + */ + public func hideSideMenu() { + dismissNavigationMenu() + } + + /** + Embeds menu item content view controller. + + - parameter selectedContentVC: The view controller to be embedded. + */ + public func selectContentViewController(_ selectedContentVC: UIViewController) { + if let currentContentVC = currentContentViewController { + if currentContentVC != selectedContentVC { + currentContentVC.view.removeFromSuperview() + currentContentVC.removeFromParentViewController() + setCurrentView(selectedContentVC) + } + } else { + setCurrentView(selectedContentVC) + } + } +} + +// MARK: - Private +fileprivate extension MenuContainerViewController { /** Adds proper content view controller as a child. - parameter selectedContentVC: The view controller to be added. */ - private func setCurrentView(_ selectedContentVC: UIViewController) { + func setCurrentView(_ selectedContentVC: UIViewController) { addChildViewController(selectedContentVC) view.addSubviewWithFullSizeConstraints(view: selectedContentVC.view) currentContentViewController = selectedContentVC @@ -151,7 +169,7 @@ open class MenuContainerViewController: UIViewController { /** Presents left side menu. */ - private func presentNavigationMenu() { + func presentNavigationMenu() { if menuViewController == nil { fatalError("Invalid `menuViewController` value. It should not be nil") } @@ -162,7 +180,7 @@ open class MenuContainerViewController: UIViewController { /** Dismisses left side menu. */ - private func dismissNavigationMenu() { + func dismissNavigationMenu() { self.dismiss(animated: true, completion: nil) isShown = false } @@ -179,5 +197,16 @@ extension UIView { addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["view": view])) addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["view": view])) + +// let top: NSLayoutConstraint +// if #available(iOS 11.0, *) { +// top = view.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor) +// } else { +// top = view.topAnchor.constraint(equalTo: self.topAnchor) +// } +// let leading = view.leadingAnchor.constraint(equalTo: self.leadingAnchor) +// let trailing = self.trailingAnchor.constraint(equalTo: view.trailingAnchor) +// let bottom = self.bottomAnchor.constraint(equalTo: view.bottomAnchor) +// NSLayoutConstraint.activate([top, leading, trailing, bottom]) } } diff --git a/Sources/MenuTransitioningDelegate.swift b/Sources/MenuTransitioningDelegate.swift index 06fb327..1715f07 100644 --- a/Sources/MenuTransitioningDelegate.swift +++ b/Sources/MenuTransitioningDelegate.swift @@ -25,6 +25,12 @@ final class MenuTransitioningDelegate: NSObject { let interactiveTransition: MenuInteractiveTransition + public var shadowOptions = SideMenuItemShadow() { + didSet { + interactiveTransition.shadowOptions = shadowOptions + } + } + init(interactiveTransition: MenuInteractiveTransition) { self.interactiveTransition = interactiveTransition } diff --git a/Sources/MenuItemContentViewController.swift b/Sources/SideMenuItemContent.swift similarity index 100% rename from Sources/MenuItemContentViewController.swift rename to Sources/SideMenuItemContent.swift diff --git a/Sources/SideMenuItemShadow.swift b/Sources/SideMenuItemShadow.swift new file mode 100644 index 0000000..7f6373c --- /dev/null +++ b/Sources/SideMenuItemShadow.swift @@ -0,0 +1,18 @@ +// +// SideMenuItemShadow.swift +// InteractiveSideMenu +// +// Created by Eric Miller on 2/8/18. +// Copyright © 2018 Handsome. All rights reserved. +// + +import Foundation + +/** + Defines the parameters for the shadow that is shown under to content controller when the side menu is open. +*/ +public struct SideMenuItemShadow { + public var color: UIColor? = UIColor.black + public var opacity: CGFloat = 0.3 + public var offset: CGSize = CGSize(width: -5, height: 5) +} From 691f5941c0d7bafc5c04c58fff98f5d7e8aaae1f Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Thu, 8 Feb 2018 14:13:53 -0600 Subject: [PATCH 2/9] Update change log --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 640a1e5..7fd55c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes of the library will be documented in this file. +## 2.2 +### Added +- Ability to globally change the drop shadow of the current content view while the menu is open (#61) + ## 2.1 - [2017-10-23] ### Added - Swift 4 support From cbb2db534508d691f9ffe75e4ff7a8c3084faced Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Thu, 8 Feb 2018 14:21:43 -0600 Subject: [PATCH 3/9] Add public initializer for SideMenuItemShadow --- Sources/SideMenuItemShadow.swift | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/Sources/SideMenuItemShadow.swift b/Sources/SideMenuItemShadow.swift index 7f6373c..b0d06fe 100644 --- a/Sources/SideMenuItemShadow.swift +++ b/Sources/SideMenuItemShadow.swift @@ -12,7 +12,24 @@ import Foundation Defines the parameters for the shadow that is shown under to content controller when the side menu is open. */ public struct SideMenuItemShadow { - public var color: UIColor? = UIColor.black - public var opacity: CGFloat = 0.3 - public var offset: CGSize = CGSize(width: -5, height: 5) + + struct Defaults { + static var defaultColor: UIColor = UIColor.black + static var defaultOpacity: CGFloat = 0.3 + static var defaultSize: CGSize = CGSize(width: -5, height: 5) + } + + public var color: UIColor? = Defaults.defaultColor + public var opacity: CGFloat = Defaults.defaultOpacity + public var offset: CGSize = Defaults.defaultSize + + public init() { } + + public init(color: UIColor? = Defaults.defaultColor, + opacity: CGFloat = Defaults.defaultOpacity, + offset: CGSize = Defaults.defaultSize) { + self.color = color + self.opacity = opacity + self.offset = offset + } } From dc8fa6796ddab4b76f4c58bf4b1951c38f62922c Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Fri, 9 Feb 2018 07:12:14 -0600 Subject: [PATCH 4/9] Update to sample project to make the side menu appear more like the demo gif --- Sample/Sample.xcodeproj/project.pbxproj | 12 +- .../kitten_avatar.imageset/Contents.json | 21 ++++ .../kitten_avatar.imageset/kitten_avatar.jpeg | Bin 0 -> 5189 bytes Sample/Sample/Base.lproj/Main.storyboard | 90 +++++++++++---- .../Sample/NavigationMenuViewController.swift | 70 ------------ Sample/Sample/SampleMenuViewController.swift | 107 ++++++++++++++++++ Sample/Sample/SampleTableCell.swift | 27 +++++ 7 files changed, 234 insertions(+), 93 deletions(-) create mode 100644 Sample/Sample/Assets.xcassets/kitten_avatar.imageset/Contents.json create mode 100644 Sample/Sample/Assets.xcassets/kitten_avatar.imageset/kitten_avatar.jpeg delete mode 100644 Sample/Sample/NavigationMenuViewController.swift create mode 100644 Sample/Sample/SampleMenuViewController.swift create mode 100644 Sample/Sample/SampleTableCell.swift diff --git a/Sample/Sample.xcodeproj/project.pbxproj b/Sample/Sample.xcodeproj/project.pbxproj index 4a5ceef..b9c3527 100644 --- a/Sample/Sample.xcodeproj/project.pbxproj +++ b/Sample/Sample.xcodeproj/project.pbxproj @@ -13,10 +13,11 @@ 881EF0B21E3102E30035DEB4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 881EF0B01E3102E30035DEB4 /* LaunchScreen.storyboard */; }; 881EF0BD1E31037D0035DEB4 /* KittyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881EF0B91E31037D0035DEB4 /* KittyViewController.swift */; }; 881EF0BE1E31037D0035DEB4 /* HostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881EF0BA1E31037D0035DEB4 /* HostViewController.swift */; }; - 881EF0BF1E31037D0035DEB4 /* NavigationMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881EF0BB1E31037D0035DEB4 /* NavigationMenuViewController.swift */; }; + 881EF0BF1E31037D0035DEB4 /* SampleMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881EF0BB1E31037D0035DEB4 /* SampleMenuViewController.swift */; }; 9A15C5481EDD62BC00C4FD75 /* InteractiveSideMenu.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 881EF0C71E31049C0035DEB4 /* InteractiveSideMenu.framework */; }; 9A15C5491EDD62BC00C4FD75 /* InteractiveSideMenu.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 881EF0C71E31049C0035DEB4 /* InteractiveSideMenu.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9A6755031EA8E30C00F0C71D /* TabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A6755021EA8E30C00F0C71D /* TabBarViewController.swift */; }; + D4028937202CEC45009F1262 /* SampleTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4028936202CEC45009F1262 /* SampleTableCell.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -66,9 +67,10 @@ 881EF0B31E3102E30035DEB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 881EF0B91E31037D0035DEB4 /* KittyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KittyViewController.swift; sourceTree = ""; }; 881EF0BA1E31037D0035DEB4 /* HostViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = HostViewController.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; - 881EF0BB1E31037D0035DEB4 /* NavigationMenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationMenuViewController.swift; sourceTree = ""; }; + 881EF0BB1E31037D0035DEB4 /* SampleMenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleMenuViewController.swift; sourceTree = ""; }; 881EF0C21E31049C0035DEB4 /* InteractiveSideMenu.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = InteractiveSideMenu.xcodeproj; path = ../InteractiveSideMenu.xcodeproj; sourceTree = ""; }; 9A6755021EA8E30C00F0C71D /* TabBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabBarViewController.swift; sourceTree = ""; }; + D4028936202CEC45009F1262 /* SampleTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleTableCell.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -105,8 +107,9 @@ children = ( 881EF0C11E3103A80035DEB4 /* MenuContentScreens */, 881EF0BA1E31037D0035DEB4 /* HostViewController.swift */, - 881EF0BB1E31037D0035DEB4 /* NavigationMenuViewController.swift */, + 881EF0BB1E31037D0035DEB4 /* SampleMenuViewController.swift */, 881EF0A71E3102E30035DEB4 /* AppDelegate.swift */, + D4028936202CEC45009F1262 /* SampleTableCell.swift */, 881EF0AB1E3102E30035DEB4 /* Main.storyboard */, 881EF0AE1E3102E30035DEB4 /* Assets.xcassets */, 881EF0B01E3102E30035DEB4 /* LaunchScreen.storyboard */, @@ -225,7 +228,8 @@ files = ( 881EF0BD1E31037D0035DEB4 /* KittyViewController.swift in Sources */, 881EF0BE1E31037D0035DEB4 /* HostViewController.swift in Sources */, - 881EF0BF1E31037D0035DEB4 /* NavigationMenuViewController.swift in Sources */, + D4028937202CEC45009F1262 /* SampleTableCell.swift in Sources */, + 881EF0BF1E31037D0035DEB4 /* SampleMenuViewController.swift in Sources */, 9A6755031EA8E30C00F0C71D /* TabBarViewController.swift in Sources */, 881EF0A81E3102E30035DEB4 /* AppDelegate.swift in Sources */, ); diff --git a/Sample/Sample/Assets.xcassets/kitten_avatar.imageset/Contents.json b/Sample/Sample/Assets.xcassets/kitten_avatar.imageset/Contents.json new file mode 100644 index 0000000..10e14b7 --- /dev/null +++ b/Sample/Sample/Assets.xcassets/kitten_avatar.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "kitten_avatar.jpeg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/Sample/Assets.xcassets/kitten_avatar.imageset/kitten_avatar.jpeg b/Sample/Sample/Assets.xcassets/kitten_avatar.imageset/kitten_avatar.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..586426cfeeb02b1f976ed0afb526206c3c7ae1c0 GIT binary patch literal 5189 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 literal 0 HcmV?d00001 diff --git a/Sample/Sample/Base.lproj/Main.storyboard b/Sample/Sample/Base.lproj/Main.storyboard index 5ad94b9..fdd630e 100644 --- a/Sample/Sample/Base.lproj/Main.storyboard +++ b/Sample/Sample/Base.lproj/Main.storyboard @@ -1,19 +1,19 @@ - + - - + + - + - + @@ -51,10 +51,10 @@ - + - + @@ -63,17 +63,63 @@ - - - + + + + + + + + + + + + + + + + + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -82,15 +128,20 @@ - + - + + - - + + + + + + @@ -224,10 +275,10 @@ - + - + @@ -247,6 +298,7 @@ + diff --git a/Sample/Sample/NavigationMenuViewController.swift b/Sample/Sample/NavigationMenuViewController.swift deleted file mode 100644 index f547bc6..0000000 --- a/Sample/Sample/NavigationMenuViewController.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// NavigationMenuViewController.swift -// -// Copyright 2017 Handsome LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import UIKit -import InteractiveSideMenu - -/** - Menu controller is responsible for creating its content and showing/hiding menu using 'menuContainerViewController' property. - */ -class NavigationMenuViewController: MenuViewController { - - let kCellReuseIdentifier = "MenuCell" - let menuItems = ["Kitty", "TabBar cats"] - - @IBOutlet weak var tableView: UITableView! - - override var prefersStatusBarHidden: Bool { - return false - } - - override func viewDidLoad() { - super.viewDidLoad() - - // Select the initial row - tableView.selectRow(at: IndexPath(row: 0, section: 0), animated: false, scrollPosition: UITableViewScrollPosition.none) - } -} - -extension NavigationMenuViewController: UITableViewDelegate, UITableViewDataSource { - - func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return menuItems.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: kCellReuseIdentifier, for: indexPath) - cell.textLabel?.text = menuItems[indexPath.row] - - return cell - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - guard let menuContainerViewController = self.menuContainerViewController else { - return - } - - menuContainerViewController.selectContentViewController(menuContainerViewController.contentViewControllers[indexPath.row]) - menuContainerViewController.hideSideMenu() - } -} diff --git a/Sample/Sample/SampleMenuViewController.swift b/Sample/Sample/SampleMenuViewController.swift new file mode 100644 index 0000000..411e387 --- /dev/null +++ b/Sample/Sample/SampleMenuViewController.swift @@ -0,0 +1,107 @@ +// +// SampleMenuViewController.swift +// +// Copyright 2017 Handsome LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit +import InteractiveSideMenu + +/** + Menu controller is responsible for creating its content and showing/hiding menu using 'menuContainerViewController' property. + */ +class SampleMenuViewController: MenuViewController { + + @IBOutlet fileprivate weak var tableView: UITableView! + @IBOutlet fileprivate weak var avatarImageView: UIImageView! + @IBOutlet fileprivate weak var avatarImageViewCenterXConstraint: NSLayoutConstraint! + + private var gradientApplied: Bool = false + + override var prefersStatusBarHidden: Bool { + return false + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return .lightContent + } + + override func viewDidLoad() { + super.viewDidLoad() + + // Select the initial row + tableView.selectRow(at: IndexPath(row: 0, section: 0), animated: false, scrollPosition: UITableViewScrollPosition.none) + + avatarImageView.layer.cornerRadius = avatarImageView.frame.size.width/2 + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + if !gradientApplied { + gradientApplied = true + avatarImageViewCenterXConstraint.constant = -(menuContainerViewController?.transitionOptions.visibleContentWidth ?? 0.0)/2 + + let gradient = CAGradientLayer() + let topColor = UIColor(red: 16.0/255.0, green: 12.0/255.0, blue: 54.0/255.0, alpha: 1.0) + let bottomColor = UIColor(red: 57.0/255.0, green: 33.0/255.0, blue: 61.0/255.0, alpha: 1.0) + gradient.startPoint = CGPoint(x: 0.0, y: 0.0) + gradient.endPoint = CGPoint(x: 1.0, y: 1.0) + gradient.colors = [topColor.cgColor, bottomColor.cgColor] + gradient.frame = view.bounds + view.layer.insertSublayer(gradient, at: 0) + } + } +} + +extension SampleMenuViewController: UITableViewDelegate, UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return menuContainerViewController?.contentViewControllers.count ?? 0 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SampleTableCell.self), for: indexPath) as? SampleTableCell else { + preconditionFailure("Unregistered table view cell") + } + + cell.titleLabel.text = menuContainerViewController?.contentViewControllers[indexPath.row].title ?? "A Controller" + + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + guard let menuContainerViewController = self.menuContainerViewController else { + return + } + + menuContainerViewController.selectContentViewController(menuContainerViewController.contentViewControllers[indexPath.row]) + menuContainerViewController.hideSideMenu() + } + + func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + let v = UIView() + v.backgroundColor = UIColor.clear + return v + } + + func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + return 0.5 + } +} diff --git a/Sample/Sample/SampleTableCell.swift b/Sample/Sample/SampleTableCell.swift new file mode 100644 index 0000000..e1ec603 --- /dev/null +++ b/Sample/Sample/SampleTableCell.swift @@ -0,0 +1,27 @@ +// +// SampleTableCell.swift +// Sample +// +// Created by Eric Miller on 2/8/18. +// Copyright © 2018 Handsome. All rights reserved. +// + +import UIKit + +class SampleTableCell: UITableViewCell { + + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet private weak var selectedView: UIView! + + override func awakeFromNib() { + super.awakeFromNib() + selectionStyle = .none + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + selectedView.backgroundColor = selected ? UIColor.yellow : UIColor.clear + titleLabel.textColor = selected ? UIColor.yellow : UIColor.white + } +} From 5260b0076f35680e39420ae1ca4c49382f0c3a6a Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Fri, 9 Feb 2018 07:28:09 -0600 Subject: [PATCH 5/9] Refactor giant Main storyboard into individual components --- Sample/Sample.xcodeproj/project.pbxproj | 74 ++++- Sample/Sample/Base.lproj/Main.storyboard | 275 ------------------ .../Sample/{ => Cells}/SampleTableCell.swift | 0 .../HostViewController.swift | 15 +- .../SampleMenuViewController.storyboard | 115 ++++++++ .../SampleMenuViewController.swift | 2 +- Sample/Sample/Helpers/Storyboardable.swift | 50 ++++ .../KittyViewController.storyboard | 58 ++++ .../KittyViewController.swift | 2 +- .../TabBarViewController.storyboard | 146 ++++++++++ .../TabBarViewController.swift | 2 +- 11 files changed, 437 insertions(+), 302 deletions(-) rename Sample/Sample/{ => Cells}/SampleTableCell.swift (100%) rename Sample/Sample/{ => Controllers}/HostViewController.swift (80%) create mode 100644 Sample/Sample/Controllers/SampleMenuViewController.storyboard rename Sample/Sample/{ => Controllers}/SampleMenuViewController.swift (98%) create mode 100644 Sample/Sample/Helpers/Storyboardable.swift create mode 100644 Sample/Sample/Menu Controllers/KittyViewController.storyboard rename Sample/Sample/{ => Menu Controllers}/KittyViewController.swift (98%) create mode 100644 Sample/Sample/Menu Controllers/TabBarViewController.storyboard rename Sample/Sample/{ => Menu Controllers}/TabBarViewController.swift (98%) diff --git a/Sample/Sample.xcodeproj/project.pbxproj b/Sample/Sample.xcodeproj/project.pbxproj index b9c3527..38697c1 100644 --- a/Sample/Sample.xcodeproj/project.pbxproj +++ b/Sample/Sample.xcodeproj/project.pbxproj @@ -18,6 +18,10 @@ 9A15C5491EDD62BC00C4FD75 /* InteractiveSideMenu.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 881EF0C71E31049C0035DEB4 /* InteractiveSideMenu.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9A6755031EA8E30C00F0C71D /* TabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A6755021EA8E30C00F0C71D /* TabBarViewController.swift */; }; D4028937202CEC45009F1262 /* SampleTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4028936202CEC45009F1262 /* SampleTableCell.swift */; }; + D4C58473202DD647006EF43A /* KittyViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D4C58472202DD647006EF43A /* KittyViewController.storyboard */; }; + D4C58476202DD6B0006EF43A /* Storyboardable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C58475202DD6B0006EF43A /* Storyboardable.swift */; }; + D4C58478202DD6DF006EF43A /* TabBarViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D4C58477202DD6DF006EF43A /* TabBarViewController.storyboard */; }; + D4C5847F202DD896006EF43A /* SampleMenuViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D4C5847E202DD896006EF43A /* SampleMenuViewController.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -71,6 +75,10 @@ 881EF0C21E31049C0035DEB4 /* InteractiveSideMenu.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = InteractiveSideMenu.xcodeproj; path = ../InteractiveSideMenu.xcodeproj; sourceTree = ""; }; 9A6755021EA8E30C00F0C71D /* TabBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabBarViewController.swift; sourceTree = ""; }; D4028936202CEC45009F1262 /* SampleTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleTableCell.swift; sourceTree = ""; }; + D4C58472202DD647006EF43A /* KittyViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KittyViewController.storyboard; sourceTree = ""; }; + D4C58475202DD6B0006EF43A /* Storyboardable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storyboardable.swift; sourceTree = ""; }; + D4C58477202DD6DF006EF43A /* TabBarViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = TabBarViewController.storyboard; sourceTree = ""; }; + D4C5847E202DD896006EF43A /* SampleMenuViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = SampleMenuViewController.storyboard; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -105,34 +113,70 @@ 881EF0A61E3102E30035DEB4 /* Sample */ = { isa = PBXGroup; children = ( - 881EF0C11E3103A80035DEB4 /* MenuContentScreens */, - 881EF0BA1E31037D0035DEB4 /* HostViewController.swift */, - 881EF0BB1E31037D0035DEB4 /* SampleMenuViewController.swift */, - 881EF0A71E3102E30035DEB4 /* AppDelegate.swift */, - D4028936202CEC45009F1262 /* SampleTableCell.swift */, 881EF0AB1E3102E30035DEB4 /* Main.storyboard */, - 881EF0AE1E3102E30035DEB4 /* Assets.xcassets */, - 881EF0B01E3102E30035DEB4 /* LaunchScreen.storyboard */, - 881EF0B31E3102E30035DEB4 /* Info.plist */, + 881EF0A71E3102E30035DEB4 /* AppDelegate.swift */, + D4C5847D202DD877006EF43A /* Controllers */, + D4C5847A202DD810006EF43A /* Menu Controllers */, + D4C5847C202DD859006EF43A /* Cells */, + D4C58474202DD6A2006EF43A /* Helpers */, + D4C5847B202DD828006EF43A /* Supporting Items */, ); path = Sample; sourceTree = ""; }; - 881EF0C11E3103A80035DEB4 /* MenuContentScreens */ = { + 881EF0C31E31049C0035DEB4 /* Products */ = { + isa = PBXGroup; + children = ( + 881EF0C71E31049C0035DEB4 /* InteractiveSideMenu.framework */, + ); + name = Products; + sourceTree = ""; + }; + D4C58474202DD6A2006EF43A /* Helpers */ = { + isa = PBXGroup; + children = ( + D4C58475202DD6B0006EF43A /* Storyboardable.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + D4C5847A202DD810006EF43A /* Menu Controllers */ = { isa = PBXGroup; children = ( 881EF0B91E31037D0035DEB4 /* KittyViewController.swift */, + D4C58472202DD647006EF43A /* KittyViewController.storyboard */, 9A6755021EA8E30C00F0C71D /* TabBarViewController.swift */, + D4C58477202DD6DF006EF43A /* TabBarViewController.storyboard */, ); - name = MenuContentScreens; + path = "Menu Controllers"; sourceTree = ""; }; - 881EF0C31E31049C0035DEB4 /* Products */ = { + D4C5847B202DD828006EF43A /* Supporting Items */ = { isa = PBXGroup; children = ( - 881EF0C71E31049C0035DEB4 /* InteractiveSideMenu.framework */, + 881EF0AE1E3102E30035DEB4 /* Assets.xcassets */, + 881EF0B01E3102E30035DEB4 /* LaunchScreen.storyboard */, + 881EF0B31E3102E30035DEB4 /* Info.plist */, ); - name = Products; + name = "Supporting Items"; + sourceTree = ""; + }; + D4C5847C202DD859006EF43A /* Cells */ = { + isa = PBXGroup; + children = ( + D4028936202CEC45009F1262 /* SampleTableCell.swift */, + ); + path = Cells; + sourceTree = ""; + }; + D4C5847D202DD877006EF43A /* Controllers */ = { + isa = PBXGroup; + children = ( + 881EF0BA1E31037D0035DEB4 /* HostViewController.swift */, + 881EF0BB1E31037D0035DEB4 /* SampleMenuViewController.swift */, + D4C5847E202DD896006EF43A /* SampleMenuViewController.storyboard */, + ); + path = Controllers; sourceTree = ""; }; /* End PBXGroup section */ @@ -213,8 +257,11 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4C5847F202DD896006EF43A /* SampleMenuViewController.storyboard in Resources */, 881EF0B21E3102E30035DEB4 /* LaunchScreen.storyboard in Resources */, + D4C58473202DD647006EF43A /* KittyViewController.storyboard in Resources */, 881EF0AF1E3102E30035DEB4 /* Assets.xcassets in Resources */, + D4C58478202DD6DF006EF43A /* TabBarViewController.storyboard in Resources */, 881EF0AD1E3102E30035DEB4 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -228,6 +275,7 @@ files = ( 881EF0BD1E31037D0035DEB4 /* KittyViewController.swift in Sources */, 881EF0BE1E31037D0035DEB4 /* HostViewController.swift in Sources */, + D4C58476202DD6B0006EF43A /* Storyboardable.swift in Sources */, D4028937202CEC45009F1262 /* SampleTableCell.swift in Sources */, 881EF0BF1E31037D0035DEB4 /* SampleMenuViewController.swift in Sources */, 9A6755031EA8E30C00F0C71D /* TabBarViewController.swift in Sources */, diff --git a/Sample/Sample/Base.lproj/Main.storyboard b/Sample/Sample/Base.lproj/Main.storyboard index fdd630e..e8ee619 100644 --- a/Sample/Sample/Base.lproj/Main.storyboard +++ b/Sample/Sample/Base.lproj/Main.storyboard @@ -6,149 +6,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -167,140 +27,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Sample/Sample/SampleTableCell.swift b/Sample/Sample/Cells/SampleTableCell.swift similarity index 100% rename from Sample/Sample/SampleTableCell.swift rename to Sample/Sample/Cells/SampleTableCell.swift diff --git a/Sample/Sample/HostViewController.swift b/Sample/Sample/Controllers/HostViewController.swift similarity index 80% rename from Sample/Sample/HostViewController.swift rename to Sample/Sample/Controllers/HostViewController.swift index 779ab81..a6578df 100644 --- a/Sample/Sample/HostViewController.swift +++ b/Sample/Sample/Controllers/HostViewController.swift @@ -42,7 +42,7 @@ class HostViewController: MenuContainerViewController { self.transitionOptions = TransitionOptions(duration: 0.4, visibleContentWidth: screenSize.width / 6) // Instantiate menu view controller by identifier - self.menuViewController = self.storyboard!.instantiateViewController(withIdentifier: "NavigationMenu") as! MenuViewController + self.menuViewController = SampleMenuViewController.storyboardViewController() // Gather content items controllers self.contentViewControllers = contentControllers() @@ -66,16 +66,9 @@ class HostViewController: MenuContainerViewController { } private func contentControllers() -> [UIViewController] { - let controllersIdentifiers = ["Kitty", "TabBar"] - var contentList = [UIViewController]() + let kittyController = KittyViewController.storyboardViewController() + let tabController = TabBarViewController.storyboardTabBarController() - // Instantiate items controllers from storyboard. - for identifier in controllersIdentifiers { - if let viewController = self.storyboard?.instantiateViewController(withIdentifier: identifier) { - contentList.append(viewController) - } - } - - return contentList + return [kittyController, tabController] } } diff --git a/Sample/Sample/Controllers/SampleMenuViewController.storyboard b/Sample/Sample/Controllers/SampleMenuViewController.storyboard new file mode 100644 index 0000000..ef8d9ab --- /dev/null +++ b/Sample/Sample/Controllers/SampleMenuViewController.storyboard @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample/Sample/SampleMenuViewController.swift b/Sample/Sample/Controllers/SampleMenuViewController.swift similarity index 98% rename from Sample/Sample/SampleMenuViewController.swift rename to Sample/Sample/Controllers/SampleMenuViewController.swift index 411e387..035562d 100644 --- a/Sample/Sample/SampleMenuViewController.swift +++ b/Sample/Sample/Controllers/SampleMenuViewController.swift @@ -22,7 +22,7 @@ import InteractiveSideMenu /** Menu controller is responsible for creating its content and showing/hiding menu using 'menuContainerViewController' property. */ -class SampleMenuViewController: MenuViewController { +class SampleMenuViewController: MenuViewController, Storyboardable { @IBOutlet fileprivate weak var tableView: UITableView! @IBOutlet fileprivate weak var avatarImageView: UIImageView! diff --git a/Sample/Sample/Helpers/Storyboardable.swift b/Sample/Sample/Helpers/Storyboardable.swift new file mode 100644 index 0000000..cdef6d2 --- /dev/null +++ b/Sample/Sample/Helpers/Storyboardable.swift @@ -0,0 +1,50 @@ +// +// Storyboardable.swift +// bthere +// +// Created by Eric Miller on 11/27/17. +// Copyright © 2017 Handsome. All rights reserved. +// + +import UIKit + +protocol Storyboardable: class { + static var defaultStoryboardName: String { get } +} + +extension Storyboardable where Self: UIViewController { + static var defaultStoryboardName: String { + return String(describing: self) + } + + static func storyboardViewController() -> Self { + let storyboard = UIStoryboard(name: defaultStoryboardName, bundle: nil) + + guard let vc = storyboard.instantiateInitialViewController() as? Self else { + fatalError("Could not instantiate initial storyboard with name: \(defaultStoryboardName)") + } + + return vc + } + + static func storyboardNavigationController() -> UINavigationController { + let storyboard = UIStoryboard(name: defaultStoryboardName, bundle: nil) + + guard let nc = storyboard.instantiateInitialViewController() as? UINavigationController else { + fatalError("Could not instantiate initial storyboard with name: \(defaultStoryboardName)") + } + + return nc + } + + static func storyboardTabBarController() -> UITabBarController { + let storyboard = UIStoryboard(name: defaultStoryboardName, bundle: nil) + + guard let tc = storyboard.instantiateInitialViewController() as? UITabBarController else { + fatalError("Could not instantiate initial storyboard with name: \(defaultStoryboardName)") + } + + return tc + } +} + diff --git a/Sample/Sample/Menu Controllers/KittyViewController.storyboard b/Sample/Sample/Menu Controllers/KittyViewController.storyboard new file mode 100644 index 0000000..e5dbf17 --- /dev/null +++ b/Sample/Sample/Menu Controllers/KittyViewController.storyboard @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample/Sample/KittyViewController.swift b/Sample/Sample/Menu Controllers/KittyViewController.swift similarity index 98% rename from Sample/Sample/KittyViewController.swift rename to Sample/Sample/Menu Controllers/KittyViewController.swift index 605fe76..64f2fa6 100644 --- a/Sample/Sample/KittyViewController.swift +++ b/Sample/Sample/Menu Controllers/KittyViewController.swift @@ -22,7 +22,7 @@ import InteractiveSideMenu /* KittyViewController is a controller relevant one of the side menu items. To indicate this it adopts `SideMenuItemContent` protocol. */ -class KittyViewController: UIViewController, SideMenuItemContent { +class KittyViewController: UIViewController, SideMenuItemContent, Storyboardable { /* Show side menu on menu button click */ diff --git a/Sample/Sample/Menu Controllers/TabBarViewController.storyboard b/Sample/Sample/Menu Controllers/TabBarViewController.storyboard new file mode 100644 index 0000000..e39a64c --- /dev/null +++ b/Sample/Sample/Menu Controllers/TabBarViewController.storyboard @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample/Sample/TabBarViewController.swift b/Sample/Sample/Menu Controllers/TabBarViewController.swift similarity index 98% rename from Sample/Sample/TabBarViewController.swift rename to Sample/Sample/Menu Controllers/TabBarViewController.swift index 694838f..50278f0 100644 --- a/Sample/Sample/TabBarViewController.swift +++ b/Sample/Sample/Menu Controllers/TabBarViewController.swift @@ -22,7 +22,7 @@ import InteractiveSideMenu /* TabBarViewController is a controller relevant one of the side menu items. To indicate this it adopts `SideMenuItemContent` protocol. */ -class TabBarViewController: UITabBarController, SideMenuItemContent { +class TabBarViewController: UITabBarController, SideMenuItemContent, Storyboardable { } From d1ce93214340988b172f72d6be60e90bd6878a52 Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Fri, 9 Feb 2018 09:59:29 -0600 Subject: [PATCH 6/9] Change default contentScale to 0.86. Add new menu item controller to tweak transition options in real-time --- CHANGELOG.md | 6 + InteractiveSideMenu.xcodeproj/project.pbxproj | 4 +- Sample/Sample.xcodeproj/project.pbxproj | 12 +- .../Controllers/HostViewController.swift | 9 +- .../SampleMenuViewController.swift | 28 +-- .../KittyViewController.storyboard | 18 +- .../KittyViewController.swift | 9 +- .../TabBarViewController.storyboard | 78 +++---- .../TabBarViewController.swift | 41 ++-- .../TweakViewController.storyboard | 190 ++++++++++++++++++ .../TweakViewController.swift | 61 ++++++ Sources/MenuContainerViewController.swift | 22 +- Sources/Options.swift | 2 +- Sources/SideMenuItemContent.swift | 3 + 14 files changed, 356 insertions(+), 127 deletions(-) create mode 100644 Sample/Sample/Menu Controllers/TweakViewController.storyboard create mode 100644 Sample/Sample/Menu Controllers/TweakViewController.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fd55c0..f62572a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes of the library will be documented in this file. ## 2.2 ### Added - Ability to globally change the drop shadow of the current content view while the menu is open (#61) +- New sample project controller to tweak the transition settings +- Status bar color can now be updated on a controller by controller basis + +### Changed +- Changed default `contentScale` value from `0.88` to `0.86` +- Updated sample project to better reflect the README demo gif ## 2.1 - [2017-10-23] ### Added diff --git a/InteractiveSideMenu.xcodeproj/project.pbxproj b/InteractiveSideMenu.xcodeproj/project.pbxproj index 1941736..14e9bb8 100644 --- a/InteractiveSideMenu.xcodeproj/project.pbxproj +++ b/InteractiveSideMenu.xcodeproj/project.pbxproj @@ -278,7 +278,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = is.handsome.InteractiveSideMenu; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -300,7 +300,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = is.handsome.InteractiveSideMenu; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Sample/Sample.xcodeproj/project.pbxproj b/Sample/Sample.xcodeproj/project.pbxproj index 38697c1..8cc08aa 100644 --- a/Sample/Sample.xcodeproj/project.pbxproj +++ b/Sample/Sample.xcodeproj/project.pbxproj @@ -22,6 +22,8 @@ D4C58476202DD6B0006EF43A /* Storyboardable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C58475202DD6B0006EF43A /* Storyboardable.swift */; }; D4C58478202DD6DF006EF43A /* TabBarViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D4C58477202DD6DF006EF43A /* TabBarViewController.storyboard */; }; D4C5847F202DD896006EF43A /* SampleMenuViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D4C5847E202DD896006EF43A /* SampleMenuViewController.storyboard */; }; + D4C58482202DECB4006EF43A /* TweakViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C58481202DECB4006EF43A /* TweakViewController.swift */; }; + D4C58484202DECBB006EF43A /* TweakViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D4C58483202DECBB006EF43A /* TweakViewController.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -79,6 +81,8 @@ D4C58475202DD6B0006EF43A /* Storyboardable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storyboardable.swift; sourceTree = ""; }; D4C58477202DD6DF006EF43A /* TabBarViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = TabBarViewController.storyboard; sourceTree = ""; }; D4C5847E202DD896006EF43A /* SampleMenuViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = SampleMenuViewController.storyboard; sourceTree = ""; }; + D4C58481202DECB4006EF43A /* TweakViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TweakViewController.swift; sourceTree = ""; }; + D4C58483202DECBB006EF43A /* TweakViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = TweakViewController.storyboard; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -147,6 +151,8 @@ D4C58472202DD647006EF43A /* KittyViewController.storyboard */, 9A6755021EA8E30C00F0C71D /* TabBarViewController.swift */, D4C58477202DD6DF006EF43A /* TabBarViewController.storyboard */, + D4C58481202DECB4006EF43A /* TweakViewController.swift */, + D4C58483202DECBB006EF43A /* TweakViewController.storyboard */, ); path = "Menu Controllers"; sourceTree = ""; @@ -257,6 +263,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4C58484202DECBB006EF43A /* TweakViewController.storyboard in Resources */, D4C5847F202DD896006EF43A /* SampleMenuViewController.storyboard in Resources */, 881EF0B21E3102E30035DEB4 /* LaunchScreen.storyboard in Resources */, D4C58473202DD647006EF43A /* KittyViewController.storyboard in Resources */, @@ -280,6 +287,7 @@ 881EF0BF1E31037D0035DEB4 /* SampleMenuViewController.swift in Sources */, 9A6755031EA8E30C00F0C71D /* TabBarViewController.swift in Sources */, 881EF0A81E3102E30035DEB4 /* AppDelegate.swift in Sources */, + D4C58482202DECB4006EF43A /* TweakViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -415,7 +423,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Sample/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = is.handsome.Sample; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -429,7 +437,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Sample/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = is.handsome.Sample; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Sample/Sample/Controllers/HostViewController.swift b/Sample/Sample/Controllers/HostViewController.swift index a6578df..0abe1df 100644 --- a/Sample/Sample/Controllers/HostViewController.swift +++ b/Sample/Sample/Controllers/HostViewController.swift @@ -27,10 +27,6 @@ import InteractiveSideMenu */ class HostViewController: MenuContainerViewController { - override var preferredStatusBarStyle: UIStatusBarStyle { - return .lightContent - } - override var prefersStatusBarHidden: Bool { return false } @@ -67,8 +63,9 @@ class HostViewController: MenuContainerViewController { private func contentControllers() -> [UIViewController] { let kittyController = KittyViewController.storyboardViewController() - let tabController = TabBarViewController.storyboardTabBarController() + let tabController = TabBarViewController.storyboardNavigationController() + let tweakController = TweakViewController.storyboardNavigationController() - return [kittyController, tabController] + return [kittyController, tabController, tweakController] } } diff --git a/Sample/Sample/Controllers/SampleMenuViewController.swift b/Sample/Sample/Controllers/SampleMenuViewController.swift index 035562d..d3a5211 100644 --- a/Sample/Sample/Controllers/SampleMenuViewController.swift +++ b/Sample/Sample/Controllers/SampleMenuViewController.swift @@ -27,6 +27,7 @@ class SampleMenuViewController: MenuViewController, Storyboardable { @IBOutlet fileprivate weak var tableView: UITableView! @IBOutlet fileprivate weak var avatarImageView: UIImageView! @IBOutlet fileprivate weak var avatarImageViewCenterXConstraint: NSLayoutConstraint! + private var gradientLayer = CAGradientLayer() private var gradientApplied: Bool = false @@ -50,19 +51,22 @@ class SampleMenuViewController: MenuViewController, Storyboardable { override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - if !gradientApplied { - gradientApplied = true - avatarImageViewCenterXConstraint.constant = -(menuContainerViewController?.transitionOptions.visibleContentWidth ?? 0.0)/2 - - let gradient = CAGradientLayer() - let topColor = UIColor(red: 16.0/255.0, green: 12.0/255.0, blue: 54.0/255.0, alpha: 1.0) - let bottomColor = UIColor(red: 57.0/255.0, green: 33.0/255.0, blue: 61.0/255.0, alpha: 1.0) - gradient.startPoint = CGPoint(x: 0.0, y: 0.0) - gradient.endPoint = CGPoint(x: 1.0, y: 1.0) - gradient.colors = [topColor.cgColor, bottomColor.cgColor] - gradient.frame = view.bounds - view.layer.insertSublayer(gradient, at: 0) + avatarImageViewCenterXConstraint.constant = -(menuContainerViewController?.transitionOptions.visibleContentWidth ?? 0.0)/2 + + if gradientLayer.superlayer != nil { + gradientLayer.removeFromSuperlayer() } + let topColor = UIColor(red: 16.0/255.0, green: 12.0/255.0, blue: 54.0/255.0, alpha: 1.0) + let bottomColor = UIColor(red: 57.0/255.0, green: 33.0/255.0, blue: 61.0/255.0, alpha: 1.0) + gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0) + gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0) + gradientLayer.colors = [topColor.cgColor, bottomColor.cgColor] + gradientLayer.frame = view.bounds + view.layer.insertSublayer(gradientLayer, at: 0) + } + + deinit{ + print() } } diff --git a/Sample/Sample/Menu Controllers/KittyViewController.storyboard b/Sample/Sample/Menu Controllers/KittyViewController.storyboard index e5dbf17..0bb8b60 100644 --- a/Sample/Sample/Menu Controllers/KittyViewController.storyboard +++ b/Sample/Sample/Menu Controllers/KittyViewController.storyboard @@ -1,11 +1,13 @@ - + + + @@ -13,10 +15,6 @@ - - - - @@ -27,8 +25,8 @@ - + - - - - - - @@ -78,36 +54,12 @@ - - - - - - - - - + - - - - - - @@ -118,9 +70,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample/Sample/Menu Controllers/TabBarViewController.swift b/Sample/Sample/Menu Controllers/TabBarViewController.swift index 50278f0..d5ff291 100644 --- a/Sample/Sample/Menu Controllers/TabBarViewController.swift +++ b/Sample/Sample/Menu Controllers/TabBarViewController.swift @@ -19,42 +19,27 @@ import UIKit import InteractiveSideMenu -/* +/** TabBarViewController is a controller relevant one of the side menu items. To indicate this it adopts `SideMenuItemContent` protocol. */ class TabBarViewController: UITabBarController, SideMenuItemContent, Storyboardable { + override var preferredStatusBarStyle: UIStatusBarStyle { + return .lightContent + } + + @IBAction func openMenu(_ sender: UIBarButtonItem) { + showSideMenu() + } + } -/* +/** The first controller of tab bar. */ -class FirstViewController: UIViewController { +class FirstViewController: UIViewController { } - /* - Show menu on click if connected tab bar controller adopts proper protocol. - */ - @IBAction func openMenu(_ sender: UIButton) { - - if let menuItemViewController = self.tabBarController as? SideMenuItemContent { - menuItemViewController.showSideMenu() - } - } -} - -/* +/** The second controller of tab bar. */ -class SecondViewController: UIViewController { - - /* - Show menu on click if connected tab bar controller adopts proper protocol. - */ - @IBAction func openMenu(_ sender: UIButton) { - - if let menuItemViewController = self.tabBarController as? SideMenuItemContent { - menuItemViewController.showSideMenu() - } - } - -} +class SecondViewController: UIViewController { } diff --git a/Sample/Sample/Menu Controllers/TweakViewController.storyboard b/Sample/Sample/Menu Controllers/TweakViewController.storyboard new file mode 100644 index 0000000..91f4837 --- /dev/null +++ b/Sample/Sample/Menu Controllers/TweakViewController.storyboard @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample/Sample/Menu Controllers/TweakViewController.swift b/Sample/Sample/Menu Controllers/TweakViewController.swift new file mode 100644 index 0000000..4b3d11b --- /dev/null +++ b/Sample/Sample/Menu Controllers/TweakViewController.swift @@ -0,0 +1,61 @@ +// +// TweakViewController.swift +// Sample +// +// Created by Eric Miller on 2/9/18. +// Copyright © 2018 Handsome. All rights reserved. +// + +import UIKit +import InteractiveSideMenu + +class TweakViewController: UIViewController, SideMenuItemContent, Storyboardable { + + @IBOutlet private weak var animationDurationValueLabel: UILabel! + @IBOutlet private weak var contentScaleValueLabel: UILabel! + @IBOutlet private weak var visibilityValueLabel: UILabel! + @IBOutlet private weak var visibilitySlider: UISlider! + + override var preferredStatusBarStyle: UIStatusBarStyle { + return .default + } + + override func viewDidLoad() { + super.viewDidLoad() + + visibilitySlider.maximumValue = Float(UIScreen.main.bounds.width) + if let navController = parent as? UINavigationController, + let menuContainerController = navController.parent as? MenuContainerViewController { + visibilitySlider.value = Float(menuContainerController.transitionOptions.visibleContentWidth) + visibilityValueLabel.text = "\(menuContainerController.transitionOptions.visibleContentWidth)" + } + } + + @IBAction func openMenu(_ sender: UIBarButtonItem) { + showSideMenu() + } + + @IBAction func animationDurationDidChange(_ slider: UISlider) { + animationDurationValueLabel.text = "\(TimeInterval(slider.value))" + if let navController = parent as? UINavigationController, + let menuContainerController = navController.parent as? MenuContainerViewController { + menuContainerController.transitionOptions.duration = TimeInterval(slider.value) + } + } + + @IBAction func contentScaleDidChange(_ slider: UISlider) { + contentScaleValueLabel.text = "\(CGFloat(slider.value))" + if let navController = parent as? UINavigationController, + let menuContainerController = navController.parent as? MenuContainerViewController { + menuContainerController.transitionOptions.contentScale = CGFloat(slider.value) + } + } + + @IBAction func visibilityDidChange(_ slider: UISlider) { + visibilityValueLabel.text = "\(CGFloat(slider.value))" + if let navController = parent as? UINavigationController, + let menuContainerController = navController.parent as? MenuContainerViewController { + menuContainerController.transitionOptions.visibleContentWidth = CGFloat(slider.value) + } + } +} diff --git a/Sources/MenuContainerViewController.swift b/Sources/MenuContainerViewController.swift index 0316a27..3feddff 100644 --- a/Sources/MenuContainerViewController.swift +++ b/Sources/MenuContainerViewController.swift @@ -23,6 +23,10 @@ import UIKit */ open class MenuContainerViewController: UIViewController { + open override var preferredStatusBarStyle: UIStatusBarStyle { + return currentContentViewController?.preferredStatusBarStyle ?? .lightContent + } + fileprivate weak var currentContentViewController: UIViewController? fileprivate var navigationMenuTransitionDelegate: MenuTransitioningDelegate! @@ -195,18 +199,10 @@ extension UIView { view.translatesAutoresizingMaskIntoConstraints = false insertSubview(view, at: atIndex) - addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["view": view])) - addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["view": view])) - -// let top: NSLayoutConstraint -// if #available(iOS 11.0, *) { -// top = view.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor) -// } else { -// top = view.topAnchor.constraint(equalTo: self.topAnchor) -// } -// let leading = view.leadingAnchor.constraint(equalTo: self.leadingAnchor) -// let trailing = self.trailingAnchor.constraint(equalTo: view.trailingAnchor) -// let bottom = self.bottomAnchor.constraint(equalTo: view.bottomAnchor) -// NSLayoutConstraint.activate([top, leading, trailing, bottom]) + let top = view.topAnchor.constraint(equalTo: self.topAnchor) + let leading = view.leadingAnchor.constraint(equalTo: self.leadingAnchor) + let trailing = self.trailingAnchor.constraint(equalTo: view.trailingAnchor) + let bottom = self.bottomAnchor.constraint(equalTo: view.bottomAnchor) + NSLayoutConstraint.activate([top, leading, trailing, bottom]) } } diff --git a/Sources/Options.swift b/Sources/Options.swift index 98a305e..e77836f 100644 --- a/Sources/Options.swift +++ b/Sources/Options.swift @@ -97,7 +97,7 @@ public struct TransitionOptions { /// Regular view animation options. Default value is `curveEaseInOut`. public var animationOptions: UIViewAnimationOptions = .curveEaseInOut - public init(duration: TimeInterval = 0.5, contentScale: CGFloat = 0.88, visibleContentWidth: CGFloat = 56.0) { + public init(duration: TimeInterval = 0.5, contentScale: CGFloat = 0.86, visibleContentWidth: CGFloat = 56.0) { self.duration = duration self.contentScale = contentScale self.visibleContentWidth = visibleContentWidth diff --git a/Sources/SideMenuItemContent.swift b/Sources/SideMenuItemContent.swift index 3a56d80..39bece2 100644 --- a/Sources/SideMenuItemContent.swift +++ b/Sources/SideMenuItemContent.swift @@ -37,6 +37,9 @@ extension SideMenuItemContent where Self: UIViewController { public func showSideMenu() { if let menuContainerViewController = parent as? MenuContainerViewController { menuContainerViewController.showSideMenu() + } else if let navController = parent as? UINavigationController, + let menuContainerViewController = navController.parent as? MenuContainerViewController { + menuContainerViewController.showSideMenu() } } } From d5d6bbc0c3f542f0acb99496f42ff7ca58bce770 Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Fri, 9 Feb 2018 10:46:14 -0600 Subject: [PATCH 7/9] Update ChangeLog and Podspec --- CHANGELOG.md | 3 +++ InteractiveSideMenu.podspec | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f62572a..6f301c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ All notable changes of the library will be documented in this file. - Changed default `contentScale` value from `0.88` to `0.86` - Updated sample project to better reflect the README demo gif +### Breaking +- Dropped support for iOS 8 + ## 2.1 - [2017-10-23] ### Added - Swift 4 support diff --git a/InteractiveSideMenu.podspec b/InteractiveSideMenu.podspec index 165e01c..22368cb 100644 --- a/InteractiveSideMenu.podspec +++ b/InteractiveSideMenu.podspec @@ -1,14 +1,14 @@ Pod::Spec.new do |s| s.name = "InteractiveSideMenu" - s.version = "2.1" + s.version = "2.2" s.summary = "Interactive Side Menu in Swift" s.homepage = "https://github.com/handsomecode/InteractiveSideMenu" s.license = "Apache 2.0 license" - s.author = { "Andrey Arzhannikov" => "andreya@handsome.is" } + s.author = { "Eric Miller" => "eric@handsome.is" } s.source = { :git => "https://github.com/handsomecode/InteractiveSideMenu.git", :tag => "#{s.version}" } - s.platform = :ios, "8.0" + s.platform = :ios, "9.0" s.source_files = "Sources/*.swift" From a30ac2fe65a9292fd66bd4b479c4bc6c89a57ca2 Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Fri, 9 Feb 2018 10:50:42 -0600 Subject: [PATCH 8/9] Update Known Issues in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 45acf0b..126d0d2 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,7 @@ override func viewWillTransition(to size: CGSize, with coordinator: UIViewContro Check out the [Sample](./Sample) project for more details and usage examples. # Known Issues -There is [an issue](https://github.com/handsomecode/InteractiveSideMenu/issues/53) associated with the scaling of a UINavigationBar in iOS 11. Status bar background is hidden during side menu closing if `contentScale < 1`. This is an *iOS 11* issue and has been reported to Apple. +There is [an issue](https://github.com/handsomecode/InteractiveSideMenu/issues/53) associated with the content controller's view not properly having the `safeAreaInsets` set. This causes the view's layout to shift when the side menu is closed. The issue appears to be tied to the transition options `contentScale` setting. Choosing a value in the range 0.87 - 0.91 causes the `safeAreaInsets.top` to be set to `0.0`. The default value of the library is no longer within this range but be mindful if changing that value for your own application. # Requirements From d3f8fdc4e26def7b9c27039a343f8b1c7b5899e5 Mon Sep 17 00:00:00 2001 From: Eric Miller Date: Fri, 9 Feb 2018 10:57:27 -0600 Subject: [PATCH 9/9] Update ChangeLog with issue numbers --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f301c1..5c1b738 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes of the library will be documented in this file. - Status bar color can now be updated on a controller by controller basis ### Changed -- Changed default `contentScale` value from `0.88` to `0.86` +- Changed default `contentScale` value from `0.88` to `0.86` (#53, #66, #72) - Updated sample project to better reflect the README demo gif ### Breaking