From 658e0167efdb3efa9b079a222bc0d692b1ce430d Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Mon, 4 Jun 2018 11:18:43 +0100 Subject: [PATCH 01/16] Adding free scroll functionality that doesn't force selection when it scrolls. --- Pod/Classes/MenuView.swift | 17 +++++++++++++++-- Pod/Classes/PagingMenuController.swift | 7 ++++--- .../Protocols/MenuViewCustomizable.swift | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Pod/Classes/MenuView.swift b/Pod/Classes/MenuView.swift index 6eba4054..c0693eae 100644 --- a/Pod/Classes/MenuView.swift +++ b/Pod/Classes/MenuView.swift @@ -30,16 +30,29 @@ open class MenuView: UIScrollView { fileprivate var menuViewBounces: Bool { switch menuOptions.displayMode { case .standard(_, _, .scrollEnabledAndBouces), - .infinite(_, .scrollEnabledAndBouces): return true + .standard(_, _, .freeScroll), + .infinite(_, .scrollEnabledAndBouces), + .infinite(_, .freeScroll): return true default: return false } } + var freescroll:Bool { + switch menuOptions.displayMode { + case .standard(_, _, .freeScroll), + .infinite(_, .freeScroll): + return true + default: + return false + } + } fileprivate var menuViewScrollEnabled: Bool { switch menuOptions.displayMode { case .standard(_, _, .scrollEnabledAndBouces), .standard(_, _, .scrollEnabled), + .standard(_, _, .freeScroll), .infinite(_, .scrollEnabledAndBouces), - .infinite(_, .scrollEnabled): return true + .infinite(_, .scrollEnabled), + .infinite(_, .freeScroll): return true default: return false } } diff --git a/Pod/Classes/PagingMenuController.swift b/Pod/Classes/PagingMenuController.swift index e8344a5f..51b0f962 100644 --- a/Pod/Classes/PagingMenuController.swift +++ b/Pod/Classes/PagingMenuController.swift @@ -322,8 +322,9 @@ extension PagingMenuController: UIScrollViewDelegate { nextPage = nextPageFromCurrentPoint default: return } - - move(toPage: nextPage) + if !(menuView?.freescroll ?? false) { + move(toPage: nextPage) + } } public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { @@ -332,7 +333,7 @@ extension PagingMenuController: UIScrollViewDelegate { public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { switch (scrollView, decelerate) { - case (let scrollView, false) where scrollView.isEqual(menuView): break + case (let scrollView, false) where scrollView.isEqual(menuView) && !(menuView?.freescroll ?? false): break default: return } diff --git a/Pod/Classes/Protocols/MenuViewCustomizable.swift b/Pod/Classes/Protocols/MenuViewCustomizable.swift index 376006b0..07db5d3c 100644 --- a/Pod/Classes/Protocols/MenuViewCustomizable.swift +++ b/Pod/Classes/Protocols/MenuViewCustomizable.swift @@ -74,6 +74,7 @@ public enum MenuScrollingMode { case scrollEnabled case scrollEnabledAndBouces case pagingEnabled + case freeScroll } public enum MenuFocusMode { From 380fbeb0884d853ae42328d874d560516697e856 Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Mon, 4 Jun 2018 11:22:55 +0100 Subject: [PATCH 02/16] Swift 4.1 compatibility --- .../project.pbxproj | 32 +++++++++++++++++-- .../xcschemes/PagingMenuController.xcscheme | 13 +++++--- PagingMenuController/Info.plist | 2 +- Pod/Classes/MenuItemView.swift | 2 +- Pod/Classes/PagingMenuController.swift | 4 +-- 5 files changed, 41 insertions(+), 12 deletions(-) diff --git a/PagingMenuController.xcodeproj/project.pbxproj b/PagingMenuController.xcodeproj/project.pbxproj index 24d3a90e..963bc06c 100644 --- a/PagingMenuController.xcodeproj/project.pbxproj +++ b/PagingMenuController.xcodeproj/project.pbxproj @@ -132,7 +132,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = kitasuke; TargetAttributes = { ECE530661B6DEB18001CF201 = { @@ -194,13 +194,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -208,6 +218,7 @@ CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -243,13 +254,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -269,6 +290,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; @@ -281,6 +303,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -289,10 +312,11 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.yusuke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -300,6 +324,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -308,9 +333,10 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.yusuke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; diff --git a/PagingMenuController.xcodeproj/xcshareddata/xcschemes/PagingMenuController.xcscheme b/PagingMenuController.xcodeproj/xcshareddata/xcschemes/PagingMenuController.xcscheme index 4a4595cd..a9d5489f 100644 --- a/PagingMenuController.xcodeproj/xcshareddata/xcschemes/PagingMenuController.xcscheme +++ b/PagingMenuController.xcodeproj/xcshareddata/xcschemes/PagingMenuController.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -62,15 +62,18 @@ ReferencedContainer = "container:PagingMenuController.xcodeproj"> + + CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.yusuke.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Pod/Classes/MenuItemView.swift b/Pod/Classes/MenuItemView.swift index 44e92278..ccd07e59 100644 --- a/Pod/Classes/MenuItemView.swift +++ b/Pod/Classes/MenuItemView.swift @@ -303,7 +303,7 @@ extension MenuItemView { fileprivate func estimatedLabelSize(_ label: UILabel) -> CGSize { guard let text = label.text else { return .zero } - return NSString(string: text).boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: label.font], context: nil).size + return NSString(string: text).boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [kCTFontAttributeName as NSAttributedStringKey: label.font], context: nil).size } fileprivate func calculateLabelSize(_ label: UILabel, maxWidth: CGFloat) -> CGSize { diff --git a/Pod/Classes/PagingMenuController.swift b/Pod/Classes/PagingMenuController.swift index 51b0f962..cca16222 100644 --- a/Pod/Classes/PagingMenuController.swift +++ b/Pod/Classes/PagingMenuController.swift @@ -479,7 +479,7 @@ extension PagingMenuController { menuView?.addGestureRecognizer(rightSwipeGestureRecognizer) } - internal func handleTapGesture(_ recognizer: UITapGestureRecognizer) { + @objc internal func handleTapGesture(_ recognizer: UITapGestureRecognizer) { guard let menuItemView = recognizer.view as? MenuItemView, let menuView = menuView, let page = menuView.menuItemViews.index(of: menuItemView), @@ -504,7 +504,7 @@ extension PagingMenuController { move(toPage: newPage) } - internal func handleSwipeGesture(_ recognizer: UISwipeGestureRecognizer) { + @objc internal func handleSwipeGesture(_ recognizer: UISwipeGestureRecognizer) { guard let menuView = recognizer.view as? MenuView, let menuOptions = menuOptions else { return } From 419a2fe8adb53fe616a60d4477260a8c7978e248 Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Mon, 4 Jun 2018 11:56:49 +0100 Subject: [PATCH 03/16] Fixing the underline not showing when the option selectedItemCenter != true --- Pod/Classes/MenuView.swift | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Pod/Classes/MenuView.swift b/Pod/Classes/MenuView.swift index c0693eae..8503d5f4 100644 --- a/Pod/Classes/MenuView.swift +++ b/Pod/Classes/MenuView.swift @@ -142,9 +142,7 @@ open class MenuView: UIScrollView { let duration = animated ? menuOptions.animationDuration : 0 UIView.animate(withDuration: duration, animations: { [unowned self] () -> Void in self.focusMenuItem() - if self.menuOptions.selectedItemCenter { - self.positionMenuItemViews() - } + self.positionMenuItemViews() }) { [weak self] (_) in guard let _ = self else { return } @@ -152,9 +150,8 @@ open class MenuView: UIScrollView { if case .infinite = self!.menuOptions.displayMode { self!.relayoutMenuItemViews() } - if self!.menuOptions.selectedItemCenter { - self!.positionMenuItemViews() - } + self!.positionMenuItemViews() + self!.setNeedsLayout() self!.layoutIfNeeded() @@ -322,7 +319,9 @@ open class MenuView: UIScrollView { } fileprivate func positionMenuItemViews() { - contentOffset.x = contentOffsetX + if self.menuOptions.selectedItemCenter { + contentOffset.x = contentOffsetX + } animateUnderlineViewIfNeeded() animateRoundRectViewIfNeeded() } From d809b9daae2ff6663f1e80fffc7eedcdb9076289 Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Mon, 4 Jun 2018 16:06:13 +0100 Subject: [PATCH 04/16] adding check when navigation throughout the ViewControllers --- Pod/Classes/MenuView.swift | 3 ++- Pod/Classes/PagingMenuController.swift | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Pod/Classes/MenuView.swift b/Pod/Classes/MenuView.swift index 8503d5f4..e854af78 100644 --- a/Pod/Classes/MenuView.swift +++ b/Pod/Classes/MenuView.swift @@ -319,7 +319,8 @@ open class MenuView: UIScrollView { } fileprivate func positionMenuItemViews() { - if self.menuOptions.selectedItemCenter { + let item = self.currentMenuItemView.frame + if self.menuOptions.selectedItemCenter || !bounds.contains(item) { contentOffset.x = contentOffsetX } animateUnderlineViewIfNeeded() diff --git a/Pod/Classes/PagingMenuController.swift b/Pod/Classes/PagingMenuController.swift index cca16222..01abb835 100644 --- a/Pod/Classes/PagingMenuController.swift +++ b/Pod/Classes/PagingMenuController.swift @@ -314,15 +314,17 @@ extension PagingMenuController: UIScrollViewDelegate { public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { onMove?(.didScrollEnd) + var contentScrollView:Bool = false let nextPage: Int switch (scrollView, pagingViewController, menuView) { case let (scrollView, pagingViewController?, _) where scrollView.isEqual(pagingViewController.contentScrollView): nextPage = nextPageFromCurrentPosition + contentScrollView = true case let (scrollView, _, menuView?) where scrollView.isEqual(menuView): nextPage = nextPageFromCurrentPoint default: return } - if !(menuView?.freescroll ?? false) { + if !(menuView?.freescroll ?? false) || contentScrollView { move(toPage: nextPage) } } From ad0e7abc1bde49cee7639cd87ef4d5673e2085bb Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Wed, 27 Jun 2018 10:01:49 +0100 Subject: [PATCH 05/16] turning the menu public to be able to reuse --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ Pod/Classes/MenuView.swift | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 PagingMenuController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/PagingMenuController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PagingMenuController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/PagingMenuController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Pod/Classes/MenuView.swift b/Pod/Classes/MenuView.swift index e854af78..7e696ef2 100644 --- a/Pod/Classes/MenuView.swift +++ b/Pod/Classes/MenuView.swift @@ -91,7 +91,7 @@ open class MenuView: UIScrollView { fileprivate var currentIndex: Int = 0 // MARK: - Lifecycle - internal init(menuOptions: MenuViewCustomizable) { + public init(menuOptions: MenuViewCustomizable) { super.init(frame: CGRect(x: 0, y: 0, width: 0, height: menuOptions.height)) self.menuOptions = menuOptions @@ -122,7 +122,7 @@ open class MenuView: UIScrollView { // MARK: - Internal method - internal func move(toPage page: Int, animated: Bool = true) { + func move(toPage page: Int, animated: Bool = true) { // hide menu view when constructing itself if !animated { alpha = 0 From f6b44873d358ea5f849e9d122c3c0977483cef2c Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Wed, 27 Jun 2018 10:01:49 +0100 Subject: [PATCH 06/16] turning the menu public to be able to reuse --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ Pod/Classes/MenuView.swift | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 PagingMenuController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/PagingMenuController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PagingMenuController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/PagingMenuController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Pod/Classes/MenuView.swift b/Pod/Classes/MenuView.swift index e854af78..719e96ed 100644 --- a/Pod/Classes/MenuView.swift +++ b/Pod/Classes/MenuView.swift @@ -91,7 +91,7 @@ open class MenuView: UIScrollView { fileprivate var currentIndex: Int = 0 // MARK: - Lifecycle - internal init(menuOptions: MenuViewCustomizable) { + public init(menuOptions: MenuViewCustomizable) { super.init(frame: CGRect(x: 0, y: 0, width: 0, height: menuOptions.height)) self.menuOptions = menuOptions @@ -122,7 +122,7 @@ open class MenuView: UIScrollView { // MARK: - Internal method - internal func move(toPage page: Int, animated: Bool = true) { + public func move(toPage page: Int, animated: Bool = true) { // hide menu view when constructing itself if !animated { alpha = 0 From 30cc50e874b995ca0e70877a11e8c624a6faf6d1 Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Fri, 7 Dec 2018 12:19:41 +0000 Subject: [PATCH 07/16] adapting customization with public properties --- Pod/Classes/MenuView.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Pod/Classes/MenuView.swift b/Pod/Classes/MenuView.swift index 719e96ed..02269421 100644 --- a/Pod/Classes/MenuView.swift +++ b/Pod/Classes/MenuView.swift @@ -11,10 +11,10 @@ import UIKit open class MenuView: UIScrollView { public fileprivate(set) var currentMenuItemView: MenuItemView! - internal fileprivate(set) var menuItemViews = [MenuItemView]() + public fileprivate(set) var menuItemViews = [MenuItemView]() internal var onMove: ((MenuMoveState) -> Void)? - fileprivate var menuOptions: MenuViewCustomizable! + public var menuOptions: MenuViewCustomizable! fileprivate var sortedMenuItemViews = [MenuItemView]() fileprivate let contentView: UIView = { $0.translatesAutoresizingMaskIntoConstraints = false @@ -363,13 +363,13 @@ open class MenuView: UIScrollView { } extension MenuView: Pagable { - var currentPage: Int { + public var currentPage: Int { return currentIndex } - var previousPage: Int { + public var previousPage: Int { return currentPage - 1 < 0 ? menuItemCount - 1 : currentPage - 1 } - var nextPage: Int { + public var nextPage: Int { return currentPage + 1 > menuItemCount - 1 ? 0 : currentPage + 1 } func update(currentPage page: Int) { From 988f0d8c2ca10f92199c26209fea82ac1f63bb25 Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Wed, 31 Jul 2019 17:19:06 +0100 Subject: [PATCH 08/16] Adding effect to move the bar below the item when moving the pages --- Pod/Classes/MenuItemView.swift | 2 +- Pod/Classes/MenuView.swift | 34 ++++++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Pod/Classes/MenuItemView.swift b/Pod/Classes/MenuItemView.swift index ccd07e59..54827c7c 100644 --- a/Pod/Classes/MenuItemView.swift +++ b/Pod/Classes/MenuItemView.swift @@ -58,7 +58,7 @@ open class MenuItemView: UIView { return imageView }() - fileprivate var menuOptions: MenuViewCustomizable! + fileprivate(set) var menuOptions: MenuViewCustomizable! fileprivate var menuItemOptions: MenuItemViewCustomizable! fileprivate var widthConstraint: NSLayoutConstraint! fileprivate var descriptionWidthConstraint: NSLayoutConstraint! diff --git a/Pod/Classes/MenuView.swift b/Pod/Classes/MenuView.swift index 719e96ed..04113b76 100644 --- a/Pod/Classes/MenuView.swift +++ b/Pod/Classes/MenuView.swift @@ -11,10 +11,10 @@ import UIKit open class MenuView: UIScrollView { public fileprivate(set) var currentMenuItemView: MenuItemView! - internal fileprivate(set) var menuItemViews = [MenuItemView]() + public fileprivate(set) var menuItemViews = [MenuItemView]() internal var onMove: ((MenuMoveState) -> Void)? - fileprivate var menuOptions: MenuViewCustomizable! + public var menuOptions: MenuViewCustomizable! fileprivate var sortedMenuItemViews = [MenuItemView]() fileprivate let contentView: UIView = { $0.translatesAutoresizingMaskIntoConstraints = false @@ -121,6 +121,20 @@ open class MenuView: UIScrollView { } // MARK: - Internal method + public func scrollBetween(toPage: Int, percent:CGFloat){ + guard toPage >= 0 && toPage < menuItemViews.count else { + return + } + guard case .underline(_, _, let horizontalPadding, _) = menuOptions.focusMode else { return } + let previousFrame = menuItemViews[currentPage].frame + let targetFrame = menuItemViews[toPage].frame + let differencePos = ((targetFrame.minX - previousFrame.minX)*percent) + let differenceSize = (previousFrame.width*(1-percent) + targetFrame.width*percent) + // print(differenceSize) + underlineView.frame.origin.x = previousFrame.minX + differencePos + horizontalPadding + underlineView.frame.size.width = differenceSize - horizontalPadding * 2 + + } public func move(toPage page: Int, animated: Bool = true) { // hide menu view when constructing itself @@ -173,7 +187,7 @@ open class MenuView: UIScrollView { } setNeedsLayout() layoutIfNeeded() - + animateUnderlineViewIfNeeded() animateRoundRectViewIfNeeded() } @@ -215,7 +229,7 @@ open class MenuView: UIScrollView { contentView.heightAnchor.constraint(equalTo: heightAnchor) ]) } - + fileprivate func constructMenuItemViews(_ menuOptions: MenuViewCustomizable) { constructMenuItemViews({ return MenuItemView(menuOptions: menuOptions, menuItemOptions: menuOptions.itemsOptions[$0], addDiveder: $1) @@ -312,12 +326,12 @@ open class MenuView: UIScrollView { roundRectView.frame.origin.x = targetFrame.minX + horizontalPadding roundRectView.frame.size.width = targetFrame.width - horizontalPadding * 2 } - + fileprivate func relayoutMenuItemViews() { sortMenuItemViews() layoutMenuItemViews() } - + fileprivate func positionMenuItemViews() { let item = self.currentMenuItemView.frame if self.menuOptions.selectedItemCenter || !bounds.contains(item) { @@ -353,7 +367,7 @@ open class MenuView: UIScrollView { self.currentMenuItemView = $0 } } - + // make selected item foreground sortedMenuItemViews.forEach { $0.layer.zPosition = isSelected($0) ? 0 : -1 } @@ -363,13 +377,13 @@ open class MenuView: UIScrollView { } extension MenuView: Pagable { - var currentPage: Int { + public var currentPage: Int { return currentIndex } - var previousPage: Int { + public var previousPage: Int { return currentPage - 1 < 0 ? menuItemCount - 1 : currentPage - 1 } - var nextPage: Int { + public var nextPage: Int { return currentPage + 1 > menuItemCount - 1 ? 0 : currentPage + 1 } func update(currentPage page: Int) { From bfe4a4d5ce019d8d78c911c32d2b881b2803b4d0 Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Thu, 1 Aug 2019 09:59:15 +0100 Subject: [PATCH 09/16] Adding an event for the scroll action --- Pod/Classes/PagingMenuController.swift | 29 +++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/Pod/Classes/PagingMenuController.swift b/Pod/Classes/PagingMenuController.swift index 01abb835..20ec5699 100644 --- a/Pod/Classes/PagingMenuController.swift +++ b/Pod/Classes/PagingMenuController.swift @@ -16,6 +16,7 @@ public enum MenuMoveState { case didMoveController(to: UIViewController, from: UIViewController) case willMoveItem(to: MenuItemView, from: MenuItemView) case didMoveItem(to: MenuItemView, from: MenuItemView) + case scrollingView(scrollView:UIScrollView) case didScrollStart case didScrollEnd } @@ -24,6 +25,8 @@ internal let MinimumSupportedViewCount = 1 internal let VisiblePagingViewNumber = 3 open class PagingMenuController: UIViewController { + var initialOffset:CGPoint = .zero + public fileprivate(set) var menuView: MenuView? { didSet { guard let menuView = menuView else { return } @@ -184,10 +187,10 @@ open class PagingMenuController: UIViewController { } let completionClosure = { [weak self] (_: Bool) -> Void in pagingViewController.relayoutPagingViewControllers() - + // show paging views self?.showPagingMenuControllers() - + self?.onMove?(.didMoveController(to: nextPagingViewController, from: previousPagingViewController)) } if duration > 0 { @@ -242,7 +245,7 @@ open class PagingMenuController: UIViewController { menuView.setNeedsLayout() menuView.layoutIfNeeded() } - + fileprivate func constructPagingViewController() { let viewControllers: [UIViewController] switch options.componentType { @@ -253,7 +256,7 @@ open class PagingMenuController: UIViewController { pagingViewController = PagingViewController(viewControllers: viewControllers, options: options) } - + fileprivate func layoutPagingViewController() { guard let pagingViewController = pagingViewController else { return } @@ -328,8 +331,9 @@ extension PagingMenuController: UIScrollViewDelegate { move(toPage: nextPage) } } - + public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + self.initialOffset = scrollView.contentOffset onMove?(.didScrollStart) } @@ -342,6 +346,21 @@ extension PagingMenuController: UIScrollViewDelegate { let nextPage = nextPageFromCurrentPoint move(toPage: nextPage) } + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + let percent:CGFloat + let page:Int + if initialOffset.x > scrollView.contentOffset.x { + page = currentPage - 1 + percent = (initialOffset.x - scrollView.contentOffset.x)/self.view.frame.width + }else { + page = currentPage + 1 + percent = (scrollView.contentOffset.x - initialOffset.x)/self.view.frame.width + } + print(page, percent) + menuView?.scrollBetween(toPage: page, percent: percent) + onMove?(.scrollingView(scrollView:scrollView)) + } } extension PagingMenuController: Pagable { From 598e607e75f360a52b1575c499a65c7b4664c5c9 Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Thu, 1 Aug 2019 10:00:30 +0100 Subject: [PATCH 10/16] changed the parameters of the event --- Pod/Classes/PagingMenuController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pod/Classes/PagingMenuController.swift b/Pod/Classes/PagingMenuController.swift index 20ec5699..df5d6a80 100644 --- a/Pod/Classes/PagingMenuController.swift +++ b/Pod/Classes/PagingMenuController.swift @@ -16,7 +16,7 @@ public enum MenuMoveState { case didMoveController(to: UIViewController, from: UIViewController) case willMoveItem(to: MenuItemView, from: MenuItemView) case didMoveItem(to: MenuItemView, from: MenuItemView) - case scrollingView(scrollView:UIScrollView) + case scrollingView(toPage:Int, percent:CGFloat) case didScrollStart case didScrollEnd } @@ -359,7 +359,7 @@ extension PagingMenuController: UIScrollViewDelegate { } print(page, percent) menuView?.scrollBetween(toPage: page, percent: percent) - onMove?(.scrollingView(scrollView:scrollView)) + onMove?(.scrollingView(toPage: page, percent:percent)) } } From 08d9ee271a783c55e6f9ca237fbb507f885574c1 Mon Sep 17 00:00:00 2001 From: Pedro Eugenio Antunes Date: Fri, 9 Aug 2019 10:24:40 +0100 Subject: [PATCH 11/16] Removing log --- Pod/Classes/PagingMenuController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pod/Classes/PagingMenuController.swift b/Pod/Classes/PagingMenuController.swift index df5d6a80..72aabf66 100644 --- a/Pod/Classes/PagingMenuController.swift +++ b/Pod/Classes/PagingMenuController.swift @@ -357,7 +357,7 @@ extension PagingMenuController: UIScrollViewDelegate { page = currentPage + 1 percent = (scrollView.contentOffset.x - initialOffset.x)/self.view.frame.width } - print(page, percent) +// print(page, percent) menuView?.scrollBetween(toPage: page, percent: percent) onMove?(.scrollingView(toPage: page, percent:percent)) } From 637b670b379fdc0c1dbc24f92312cc0c79221f83 Mon Sep 17 00:00:00 2001 From: Pedro Eugenio Antunes Date: Fri, 9 Aug 2019 11:07:44 +0100 Subject: [PATCH 12/16] fixo to avoid weird behaviour when clicking in the menu --- Pod/Classes/PagingMenuController.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Pod/Classes/PagingMenuController.swift b/Pod/Classes/PagingMenuController.swift index 72aabf66..8c7db9ce 100644 --- a/Pod/Classes/PagingMenuController.swift +++ b/Pod/Classes/PagingMenuController.swift @@ -141,8 +141,9 @@ open class PagingMenuController: UIViewController { constructPagingViewController() layoutPagingViewController() } - + var movingPageAutomatically = false open func move(toPage page: Int, animated: Bool = true) { + movingPageAutomatically = true switch options.componentType { case .menuView, .all: // ignore an unexpected page number @@ -192,6 +193,7 @@ open class PagingMenuController: UIViewController { self?.showPagingMenuControllers() self?.onMove?(.didMoveController(to: nextPagingViewController, from: previousPagingViewController)) + self?.movingPageAutomatically = false } if duration > 0 { UIView.animate(withDuration: duration, animations: animationClosure, completion: completionClosure) @@ -351,10 +353,10 @@ extension PagingMenuController: UIScrollViewDelegate { let percent:CGFloat let page:Int if initialOffset.x > scrollView.contentOffset.x { - page = currentPage - 1 + page = movingPageAutomatically ? currentPage : currentPage - 1 percent = (initialOffset.x - scrollView.contentOffset.x)/self.view.frame.width }else { - page = currentPage + 1 + page = movingPageAutomatically ? currentPage : currentPage + 1 percent = (scrollView.contentOffset.x - initialOffset.x)/self.view.frame.width } // print(page, percent) From f432e3975d763a6c636f2e1868e25c83e36d4690 Mon Sep 17 00:00:00 2001 From: Pedro Antunes Date: Fri, 16 Aug 2019 11:02:10 +0100 Subject: [PATCH 13/16] fixing bar was moving when scrolling menu --- Pod/Classes/PagingMenuController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Pod/Classes/PagingMenuController.swift b/Pod/Classes/PagingMenuController.swift index 8c7db9ce..9b16bcbb 100644 --- a/Pod/Classes/PagingMenuController.swift +++ b/Pod/Classes/PagingMenuController.swift @@ -350,6 +350,7 @@ extension PagingMenuController: UIScrollViewDelegate { } public func scrollViewDidScroll(_ scrollView: UIScrollView) { + guard scrollView != self.menuView else {return} let percent:CGFloat let page:Int if initialOffset.x > scrollView.contentOffset.x { @@ -359,7 +360,7 @@ extension PagingMenuController: UIScrollViewDelegate { page = movingPageAutomatically ? currentPage : currentPage + 1 percent = (scrollView.contentOffset.x - initialOffset.x)/self.view.frame.width } -// print(page, percent) + // print(page, percent) menuView?.scrollBetween(toPage: page, percent: percent) onMove?(.scrollingView(toPage: page, percent:percent)) } From 2daf25c370b9e93a246a6de1f686e2c37d59772d Mon Sep 17 00:00:00 2001 From: Kam <> Date: Tue, 13 Oct 2020 14:39:59 +0100 Subject: [PATCH 14/16] fix `movingPageAutomatically` state is incorrect --- Pod/Classes/PagingMenuController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Pod/Classes/PagingMenuController.swift b/Pod/Classes/PagingMenuController.swift index 9b16bcbb..a5d9a9b7 100644 --- a/Pod/Classes/PagingMenuController.swift +++ b/Pod/Classes/PagingMenuController.swift @@ -336,6 +336,7 @@ extension PagingMenuController: UIScrollViewDelegate { public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { self.initialOffset = scrollView.contentOffset + self.movingPageAutomatically = false onMove?(.didScrollStart) } From 09cc5163cc58add532b909112055882a4b235c7d Mon Sep 17 00:00:00 2001 From: Kam <> Date: Tue, 13 Oct 2020 18:21:32 +0100 Subject: [PATCH 15/16] blend color when scrolling --- Pod/Classes/MenuView.swift | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Pod/Classes/MenuView.swift b/Pod/Classes/MenuView.swift index 04113b76..0d15f0ad 100644 --- a/Pod/Classes/MenuView.swift +++ b/Pod/Classes/MenuView.swift @@ -126,14 +126,25 @@ open class MenuView: UIScrollView { return } guard case .underline(_, _, let horizontalPadding, _) = menuOptions.focusMode else { return } - let previousFrame = menuItemViews[currentPage].frame - let targetFrame = menuItemViews[toPage].frame + let previousMenuItem = menuItemViews[currentPage] + let previousFrame = previousMenuItem.frame + let targetMenuItem = menuItemViews[toPage] + let targetFrame = targetMenuItem.frame let differencePos = ((targetFrame.minX - previousFrame.minX)*percent) let differenceSize = (previousFrame.width*(1-percent) + targetFrame.width*percent) - // print(differenceSize) underlineView.frame.origin.x = previousFrame.minX + differencePos + horizontalPadding underlineView.frame.size.width = differenceSize - horizontalPadding * 2 + guard case .text(let title) = menuOptions.itemsOptions[0].displayMode else { return } + previousMenuItem.titleLabel.textColor = multiplyColor(title.selectedColor, by: (1-percent)) + targetMenuItem.titleLabel.textColor = multiplyColor(title.selectedColor, by: percent) + } + + ///simply put coloe function in here. + private func multiplyColor(_ color: UIColor, by multiplier: CGFloat) -> UIColor { + var (r, g, b, a) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0)) + color.getRed(&r, green: &g, blue: &b, alpha: &a) + return UIColor(red: r * multiplier, green: g * multiplier, blue: b * multiplier, alpha: a) } public func move(toPage page: Int, animated: Bool = true) { From 8ec83a52ed763c723a470d19a20327671508f587 Mon Sep 17 00:00:00 2001 From: Kam <> Date: Tue, 13 Oct 2020 18:54:56 +0100 Subject: [PATCH 16/16] with add color --- Pod/Classes/MenuView.swift | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Pod/Classes/MenuView.swift b/Pod/Classes/MenuView.swift index 0d15f0ad..de1bf445 100644 --- a/Pod/Classes/MenuView.swift +++ b/Pod/Classes/MenuView.swift @@ -136,11 +136,21 @@ open class MenuView: UIScrollView { underlineView.frame.size.width = differenceSize - horizontalPadding * 2 guard case .text(let title) = menuOptions.itemsOptions[0].displayMode else { return } - previousMenuItem.titleLabel.textColor = multiplyColor(title.selectedColor, by: (1-percent)) - targetMenuItem.titleLabel.textColor = multiplyColor(title.selectedColor, by: percent) + previousMenuItem.titleLabel.textColor = addColor(multiplyColor(title.selectedColor, by: (1-percent)), with: multiplyColor(title.color, by: percent)) + targetMenuItem.titleLabel.textColor = addColor(multiplyColor(title.selectedColor, by: percent), with: multiplyColor(title.color, by: (1-percent))) } - ///simply put coloe function in here. + private func addColor(_ color1: UIColor, with color2: UIColor) -> UIColor { + var (r1, g1, b1, a1) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0)) + var (r2, g2, b2, a2) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0)) + + color1.getRed(&r1, green: &g1, blue: &b1, alpha: &a1) + color2.getRed(&r2, green: &g2, blue: &b2, alpha: &a2) + + // add the components, but don't let them go above 1.0 + return UIColor(red: min(r1 + r2, 1), green: min(g1 + g2, 1), blue: min(b1 + b2, 1), alpha: (a1 + a2) / 2) + } + private func multiplyColor(_ color: UIColor, by multiplier: CGFloat) -> UIColor { var (r, g, b, a) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0)) color.getRed(&r, green: &g, blue: &b, alpha: &a)