From ceb6f843fd4d52d7df571e47a82f9b596a7e267e Mon Sep 17 00:00:00 2001 From: Martin Barreto Date: Wed, 20 Jan 2016 16:33:57 -0300 Subject: [PATCH] work in progress --- .../Example/ChildExampleViewController.swift | 18 +- .../SegmentedExampleViewController.swift | 4 +- .../TableChildExampleViewController.swift | 6 +- Sources/PagerTabStripError.swift | 17 + Sources/PagerTabStripSwipeDirection.swift | 15 + ...wift => PagerTabStripViewController.swift} | 328 +++++++++--------- ...SegmentedPagerTabStripViewController.swift | 123 +++++++ ...SegmentedPagerTabStripViewController.swift | 104 ------ XLPagerTabStrip.xcodeproj/project.pbxproj | 24 +- 9 files changed, 341 insertions(+), 298 deletions(-) create mode 100644 Sources/PagerTabStripError.swift create mode 100644 Sources/PagerTabStripSwipeDirection.swift rename Sources/{XLPagerTabStripViewController.swift => PagerTabStripViewController.swift} (50%) create mode 100644 Sources/SegmentedPagerTabStripViewController.swift delete mode 100644 Sources/XLSegmentedPagerTabStripViewController.swift diff --git a/Example/Example/ChildExampleViewController.swift b/Example/Example/ChildExampleViewController.swift index 3caa7e4..65bc231 100644 --- a/Example/Example/ChildExampleViewController.swift +++ b/Example/Example/ChildExampleViewController.swift @@ -9,25 +9,25 @@ import Foundation import XLPagerTabStrip -class ChildExampleViewController : UIViewController, XLPagerTabStripChildItem { +class ChildExampleViewController : UIViewController, PagerTabStripChildItem { override func viewDidLoad() { super.viewDidLoad() - let label = UILabel.init() + let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false - label.text = "XLPagertabStrip" + label.text = "XLPagerTabStrip" - self.view.addSubview(label) - self.view.backgroundColor = UIColor.whiteColor() + view.addSubview(label) + view.backgroundColor = UIColor.whiteColor() - self.view.addConstraint(NSLayoutConstraint.init(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: self.view, attribute: .CenterX, multiplier: 1.0, constant: 0.0)) - self.view.addConstraint(NSLayoutConstraint.init(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: self.view, attribute: .CenterY, multiplier: 1.0, constant: -50.0)) + view.addConstraint(NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0)) + view.addConstraint(NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: -50)) } // MARK: - XLPagerTabStripViewControllerDelegate - func childHeaderForPagerTabStripViewController(pagerTabStripController: XLPagerTabStripViewController) -> ChildHeader { - return ChildHeader(title: "View", image: nil, highlightedImage: nil, color: UIColor.whiteColor()) + func childHeaderForPagerTabStripViewController(pagerTabStripController: PagerTabStripViewController) -> ChildHeaderData { + return ChildHeaderData(title: "View", image: nil, highlightedImage: nil, color: .whiteColor()) } } diff --git a/Example/Example/SegmentedExampleViewController.swift b/Example/Example/SegmentedExampleViewController.swift index fdbd9e9..0cbbd59 100644 --- a/Example/Example/SegmentedExampleViewController.swift +++ b/Example/Example/SegmentedExampleViewController.swift @@ -9,7 +9,7 @@ import Foundation import XLPagerTabStrip -public class SegmentedExampleViewController : XLSegmentedPagerTabStripViewController{ +public class SegmentedExampleViewController : SegmentedPagerTabStripViewController{ var isReload: Bool public required init?(coder aDecoder: NSCoder) { @@ -20,7 +20,7 @@ public class SegmentedExampleViewController : XLSegmentedPagerTabStripViewContro // MARK: - XLPagerTabStripViewControllerDataSource - override public func childViewControllersForPagerTabStripViewController(pagerTabStripController: XLPagerTabStripViewController) -> [UIViewController]? { + override public func childViewControllersForPagerTabStripViewController(pagerTabStripController: PagerTabStripViewController) -> [UIViewController]? { let child_1 = TableChildExampleViewController(style: .Plain) let child_2 = ChildExampleViewController() let child_3 = TableChildExampleViewController(style: .Grouped) diff --git a/Example/Example/TableChildExampleViewController.swift b/Example/Example/TableChildExampleViewController.swift index 28b68cc..19db225 100644 --- a/Example/Example/TableChildExampleViewController.swift +++ b/Example/Example/TableChildExampleViewController.swift @@ -9,7 +9,7 @@ import Foundation import XLPagerTabStrip -class TableChildExampleViewController: UITableViewController, XLPagerTabStripChildItem { +class TableChildExampleViewController: UITableViewController, PagerTabStripChildItem { let kCellIdentifier = "postCell" var posts : [AnyObject] @@ -55,8 +55,8 @@ class TableChildExampleViewController: UITableViewController, XLPagerTabStripChi // MARK: - XLPagerTabStripChildItem - func childHeaderForPagerTabStripViewController(pagerTabStripController: XLPagerTabStripViewController) -> ChildHeader { - return ChildHeader(title: "Table View", image: nil, highlightedImage: nil, color: UIColor.whiteColor()) + func childHeaderForPagerTabStripViewController(pagerTabStripController: PagerTabStripViewController) -> ChildHeaderData { + return ChildHeaderData(title: "Table View", image: nil, highlightedImage: nil, color: .whiteColor()) } // MARK: Helpers diff --git a/Sources/PagerTabStripError.swift b/Sources/PagerTabStripError.swift new file mode 100644 index 0000000..a327752 --- /dev/null +++ b/Sources/PagerTabStripError.swift @@ -0,0 +1,17 @@ +// +// PagerTabStripError.swift +// XLPagerTabStrip +// +// Created by Martin Barreto on 1/20/16. +// +// + +import Foundation + +public enum PagerTabStripError: ErrorType { + case DataSourceMustNotBeNil + case ChildViewControllerMustConformToPagerTabStripChildItem + case CurrentIndexIsGreaterThanChildsCount + case PagerTabStripChildViewControllersMustContainAtLeastOneViewController + case ViewControllerNotContainedInPagerTabStripChildViewControllers +} \ No newline at end of file diff --git a/Sources/PagerTabStripSwipeDirection.swift b/Sources/PagerTabStripSwipeDirection.swift new file mode 100644 index 0000000..d875abe --- /dev/null +++ b/Sources/PagerTabStripSwipeDirection.swift @@ -0,0 +1,15 @@ +// +// PagerTabStripSwipeDirection.swift +// XLPagerTabStrip +// +// Created by Martin Barreto on 1/20/16. +// +// + +import Foundation + +public enum SwipeDirection { + case Left + case Right + case None +} \ No newline at end of file diff --git a/Sources/XLPagerTabStripViewController.swift b/Sources/PagerTabStripViewController.swift similarity index 50% rename from Sources/XLPagerTabStripViewController.swift rename to Sources/PagerTabStripViewController.swift index fc2f8d0..c07aa31 100644 --- a/Sources/XLPagerTabStripViewController.swift +++ b/Sources/PagerTabStripViewController.swift @@ -1,18 +1,35 @@ +// PagerTabStripViewController.swift +// XLPagerTabStrip ( https://github.com/xmartlabs/XLPagerTabStrip ) // -// XLPagerTabStripViewController.swift -// XLPagerTabStrip +// Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com ) // -// Created by Santiago on 12/30/15. -// Copyright © 2015 Xmartlabs. All rights reserved. // +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + import Foundation -public struct ChildHeader { +public struct ChildHeaderData { public var title: String public var image: UIImage? - public var highlightedImage: UIImage? +// public var highlightedImage: UIImage? public var color: UIColor? public init(title: String) { @@ -26,7 +43,7 @@ public struct ChildHeader { public init(title: String, image: UIImage?, highlightedImage: UIImage?) { self.init(title: title, image: image) - self.highlightedImage = highlightedImage +// self.highlightedImage = highlightedImage } public init(title: String, image: UIImage?, highlightedImage: UIImage?, color: UIColor?){ @@ -35,232 +52,201 @@ public struct ChildHeader { } } -public protocol XLPagerTabStripChildItem{ - func childHeaderForPagerTabStripViewController(pagerTabStripController: XLPagerTabStripViewController) -> ChildHeader +public protocol PagerTabStripChildItem { + func childHeaderForPagerTabStripViewController(pagerTabStripController: PagerTabStripViewController) -> ChildHeaderData } -public enum XLPagerTabStripDirection{ - case Left - case Right - case None +public protocol PagerTabStripViewControllerDelegate: class { + func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws + func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: Float, indexWasChanged: Bool) throws } -public protocol XLPagerTabStripViewControllerDelegate{ - func pagerTabStripViewController(pagerTabStripViewController: XLPagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex index: Int) - func pagerTabStripViewController(pagerTabStripViewController: XLPagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex index: Int, withProgressPercentage progressPercentage: Float, indexWasChanged changed: Bool) +public protocol PagerTabStripViewControllerDataSource: class { + func childViewControllersForPagerTabStripViewController(pagerTabStripController: PagerTabStripViewController) ->[UIViewController] } -public protocol XLPagerTabStripViewControllerDataSource{ - func childViewControllersForPagerTabStripViewController(pagerTabStripController: XLPagerTabStripViewController) ->[UIViewController]? -} +public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate, PagerTabStripViewControllerDataSource, PagerTabStripViewControllerDelegate { + private(set) var pagerTabStripChildViewControllers = [UIViewController]() + @IBOutlet lazy public var containerView: UIScrollView! = { [unowned self] in + let containerView = UIScrollView(frame: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds))) + containerView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] + }() + public weak var delegate: PagerTabStripViewControllerDelegate? + public weak var datasource: PagerTabStripViewControllerDataSource? -public class XLPagerTabStripViewController: UIViewController, UIScrollViewDelegate, XLPagerTabStripViewControllerDataSource, XLPagerTabStripViewControllerDelegate{ - private(set) var pagerTabStripChildViewControllers : [UIViewController]? - public var containerView: UIScrollView? - public var delegate: XLPagerTabStripViewControllerDelegate? - public var datasource: XLPagerTabStripViewControllerDataSource? - - - private(set) var currentIndex: Int = 0 - public var skipIntermediateViewControllers: Bool = false - public var isProgressiveIndicator: Bool = false - public var isElasticIndicatorLimit: Bool = false + private(set) var currentIndex = 0 + public var skipIntermediateViewControllers = false + public var isProgressiveIndicator = false + public var isElasticIndicatorLimit = false private var pagerTabStripChildViewControllersForScrolling : [UIViewController]? + private var getPagerTabStripChildViewControllersForScrolling : [UIViewController] { + return pagerTabStripChildViewControllersForScrolling ?? pagerTabStripChildViewControllers + } - private var lastPageNumber: Int = 0 - private var lastContentOffset: Float = 0.0 - private var pageBeforeRotate: Int = 0 - private var lastSize: CGSize = CGSizeMake(0, 0) + private var lastPageNumber = 0 + private var lastContentOffset: CGFloat = 0.0 + private var pageBeforeRotate = 0 + private var lastSize = CGSizeMake(0, 0) - override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?){ + + public var pageWidth: CGFloat { + return CGRectGetWidth(containerView.bounds) + } + + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - self.pagerTabStripViewControllerInit() + delegate = self + datasource = self } - required public init?(coder aDecoder: NSCoder){ + required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - self.pagerTabStripViewControllerInit() + delegate = self + datasource = self } - func pagerTabStripViewControllerInit(){ - self.delegate = self; - self.datasource = self; - } - - override public func viewDidLoad(){ + override public func viewDidLoad() { super.viewDidLoad() - - if (self.containerView == nil){ - self.containerView = UIScrollView(frame: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds))) - self.containerView?.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] - self.view.addSubview(self.containerView!) + if containerView.superview == nil { + view.addSubview(containerView!) } - - self.containerView?.bounces = true - self.containerView?.alwaysBounceHorizontal = true - self.containerView?.alwaysBounceVertical = false - self.containerView?.scrollsToTop = false - self.containerView?.delegate = self - self.containerView?.showsVerticalScrollIndicator = false - self.containerView?.showsHorizontalScrollIndicator = false - self.containerView?.pagingEnabled = true - - self.pagerTabStripChildViewControllers = self.datasource?.childViewControllersForPagerTabStripViewController(self) + containerView.bounces = true + containerView.alwaysBounceHorizontal = true + containerView.alwaysBounceVertical = false + containerView.scrollsToTop = false + containerView.delegate = self + containerView.showsVerticalScrollIndicator = false + containerView.showsHorizontalScrollIndicator = false + containerView.pagingEnabled = true + guard let dataSource = datasource else { + fatalError("dataSource must not be nil") + } + let childViewControllers = dataSource.childViewControllersForPagerTabStripViewController(self) + guard childViewControllers.count == 0 else { + fatalError("childViewControllersForPagerTabStripViewController should provide at least one child view controller") + } + pagerTabStripChildViewControllers = childViewControllers } - override public func viewDidAppear(animated: Bool){ + override public func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) - self.lastSize = self.containerView!.bounds.size - self.updateIfNeeded() + lastSize = containerView!.bounds.size + updateIfNeeded() } override public func viewDidLayoutSubviews(){ super.viewDidLayoutSubviews() - self.updateIfNeeded() - switch UIDevice.currentDevice().systemVersion.compare("8.0", options: NSStringCompareOptions.NumericSearch){ - case .OrderedAscending: - self.view.layoutSubviews() - default: break - } - + updateIfNeeded() } - public func moveToViewControllerAtIndex(index: Int){ - self.moveToViewControllerAtIndex(index, animated: true) + public func moveToViewControllerAtIndex(index: Int) { + moveToViewControllerAtIndex(index, animated: true) } - public func moveToViewControllerAtIndex(index: Int, animated: Bool){ - if (!self.isViewLoaded() || self.view.window == nil){ - self.currentIndex = index + public func moveToViewControllerAtIndex(index: Int, animated: Bool) { + guard isViewLoaded() && view.window != nil else { + currentIndex = index } - else{ - if (animated && self.skipIntermediateViewControllers && abs(self.currentIndex - index) > 1){ - var tmpChildViewControllers = self.pagerTabStripChildViewControllers - let currentChildVC = self.pagerTabStripChildViewControllers![self.currentIndex] - let fromIndex = self.currentIndex < index ? index - 1 :index + 1 - let fromChildVC = self.pagerTabStripChildViewControllers![fromIndex] - tmpChildViewControllers![self.currentIndex] = fromChildVC - tmpChildViewControllers![fromIndex] = currentChildVC - pagerTabStripChildViewControllersForScrolling = tmpChildViewControllers - self.containerView?.contentOffset = CGPointMake(self.pageOffsetForChildIndex(index: fromIndex), 0) - if((self.navigationController) != nil){ - self.navigationController?.view.userInteractionEnabled = false; - } - else{ - self.view.userInteractionEnabled = false - } - self.containerView?.contentOffset = CGPointMake(self.pageOffsetForChildIndex(index: index), 0) - } - else{ - self.containerView?.setContentOffset(CGPointMake(self.pageOffsetForChildIndex(index: index), 0), animated: true) - } + if animated && skipIntermediateViewControllers && abs(currentIndex - index) > 1 { + var tmpChildViewControllers = pagerTabStripChildViewControllers + let currentChildVC = pagerTabStripChildViewControllers[currentIndex] + let fromIndex = currentIndex < index ? index - 1 : index + 1 + let fromChildVC = pagerTabStripChildViewControllers[fromIndex] + tmpChildViewControllers[currentIndex] = fromChildVC + tmpChildViewControllers[fromIndex] = currentChildVC + pagerTabStripChildViewControllersForScrolling = tmpChildViewControllers + containerView.contentOffset = CGPointMake(pageOffsetForChildIndex(index: fromIndex), 0) + (navigationController?.view ?? view).userInteractionEnabled = false + containerView.contentOffset = CGPointMake(pageOffsetForChildIndex(index: index), 0) + } + else { + containerView.setContentOffset(CGPointMake(pageOffsetForChildIndex(index: index), 0), animated: true) } } - public func moveToViewController(viewController: UIViewController){ - self.moveToViewControllerAtIndex(self.pagerTabStripChildViewControllers!.indexOf(viewController)!) + public func moveToViewController(viewController: UIViewController) { + moveToViewControllerAtIndex(pagerTabStripChildViewControllers.indexOf(viewController)!) } - public func moveToViewController(viewController: UIViewController, animated: Bool){ - self.moveToViewControllerAtIndex(self.pagerTabStripChildViewControllers!.indexOf(viewController)!, animated: animated) + public func moveToViewController(viewController: UIViewController, animated: Bool) { + moveToViewControllerAtIndex(pagerTabStripChildViewControllers.indexOf(viewController)!, animated: animated) } - //MARK: - XLPagerTabStripViewControllerDataSource - public func childViewControllersForPagerTabStripViewController(pagerTabStripController: XLPagerTabStripViewController) -> [UIViewController]?{ - assert(false, "Sub-class must implement the XLPagerTabStripViewControllerDataSource childViewControllersForPagerTabStripViewController: method") - return nil + //MARK: - PagerTabStripViewControllerDataSource + + public func childViewControllersForPagerTabStripViewController(pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { + assertionFailure("Sub-class must implement the PagerTabStripViewControllerDataSource childViewControllersForPagerTabStripViewController: method") } - //MARK: - XLPagerTabStripViewControllerDelegate - public func pagerTabStripViewController(pagerTabStripViewController: XLPagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex index: Int){ - + //MARK: - PagerTabStripViewControllerDelegate + + public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws { } - public func pagerTabStripViewController(pagerTabStripViewController: XLPagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex index: Int, withProgressPercentage progressPercentage: Float, indexWasChanged changed: Bool){ - + public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: Float, indexWasChanged: Bool) throws { } //MARK: - Helpers - func getPagerTabStripChildViewControllersForScrolling() -> [UIViewController]?{ - if let controllers = self.pagerTabStripChildViewControllersForScrolling{ - return controllers - } - - return pagerTabStripChildViewControllers! - } - public func updateIfNeeded(){ - if (!CGSizeEqualToSize(self.lastSize, self.containerView!.bounds.size)){ - self.updateContent() + public func updateIfNeeded() { + if !CGSizeEqualToSize(lastSize, containerView!.bounds.size){ + updateContent() } } - public func scrollDirection() -> XLPagerTabStripDirection{ - if (Float(self.containerView!.contentOffset.x) > self.lastContentOffset){ - return XLPagerTabStripDirection.Left + public func swipeDirection() -> SwipeDirection { + if containerView.contentOffset.x > lastContentOffset { + return .Left } - else if (Float(self.containerView!.contentOffset.x) < self.lastContentOffset){ - return XLPagerTabStripDirection.Right + else if containerView.contentOffset.x < lastContentOffset { + return .Right } - - return XLPagerTabStripDirection.None + return .None } public func canMoveToIndex(index index: Int) -> Bool{ - return (self.currentIndex != index && self.pagerTabStripChildViewControllers?.count > index) + return currentIndex != index && pagerTabStripChildViewControllers.count > index } public func pageOffsetForChildIndex(index index: Int) -> CGFloat{ - return (CGFloat(index) * CGRectGetWidth(self.containerView!.bounds)) + return CGFloat(index) * CGRectGetWidth(containerView.bounds) } public func offsetForChildIndex(index index: Int) -> CGFloat{ - return (CGFloat(index) * CGRectGetWidth(self.containerView!.bounds) + ((CGRectGetWidth(self.containerView!.bounds) - CGRectGetWidth(self.view.bounds)) * 0.5)) - } - - enum Exception : ErrorType { - case RangeException(String) + return (CGFloat(index) * CGRectGetWidth(containerView.bounds)) + ((CGRectGetWidth(containerView.bounds) - CGRectGetWidth(view.bounds)) * 0.5) } public func offsetForChildViewController(viewController: UIViewController) throws -> CGFloat{ - if let index = self.pagerTabStripChildViewControllers?.indexOf(viewController){ - return self.offsetForChildIndex(index: index) + guard let index = self.pagerTabStripChildViewControllers.indexOf(viewController) else { + throw PagerTabStripError.ViewControllerNotContainedInPagerTabStripChildViewControllers } - - throw Exception.RangeException(NSRangeException) + return offsetForChildIndex(index: index) } - public func pageForContentOffset(contentOffset contentOffset: Float) -> Int{ + public func pageForContentOffset(contentOffset contentOffset: CGFloat) -> Int{ let result = self.virtualPageForContentOffset(contentOffset: contentOffset) return self.pageForVirtualPage(virtualPage: result) } - public func virtualPageForContentOffset(contentOffset contentOffset: Float) -> Int{ - let result: Int = Int((contentOffset + (1.5 * self.pageWidth())) / self.pageWidth()) - return result - 1 + public func virtualPageForContentOffset(contentOffset contentOffset: CGFloat) -> Int{ + return Int((contentOffset + 1.5 * pageWidth) / pageWidth) - 1 } public func pageForVirtualPage(virtualPage virtualPage: Int) -> Int{ - if (virtualPage < 0){ + if virtualPage < 0 { return 0 } - if (virtualPage > self.pagerTabStripChildViewControllers!.count - 1){ - return self.pagerTabStripChildViewControllers!.count - 1 - } + if virtualPage > pagerTabStripChildViewControllers.count - 1 { return self.pagerTabStripChildViewControllers.count - 1 } return virtualPage } - public func pageWidth() -> Float{ - return Float(CGRectGetWidth(self.containerView!.bounds)) - } - public func scrollPercentage() -> Float{ - if (self.scrollDirection() == .Left || self.scrollDirection() == .None){ - if (fmodf(Float(self.containerView!.contentOffset.x), self.pageWidth()) == 0.0){ + if swipeDirection() != .Right { + if fmod(containerView.contentOffset.x, pageWidth) == 0.0{ return 1.0 } - return fmodf(Float(self.containerView!.contentOffset.x), self.pageWidth() / self.pageWidth()) + return fmod(containerView.contentOffset.x, pageWidth) / pageWidth } return 1 - fmodf(self.containerView!.contentOffset.x >= 0 ? Float(self.containerView!.contentOffset.x) : self.pageWidth() + Float(self.containerView!.contentOffset.x), self.pageWidth()) / self.pageWidth(); } @@ -318,21 +304,21 @@ public class XLPagerTabStripViewController: UIViewController, UIScrollViewDelega self.currentIndex = newCurrentIndex let changeCurrentIndex = newCurrentIndex != oldCurrentIndex - if (self.isProgressiveIndicator){ + if isProgressiveIndicator { // FIXME: - check if delegate implements? pagerTabStripViewController(pagerTabStripViewController: XLPagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex index: Int, withProgressPercentage progressPercentage: Float, indexWasChanged changed: Bool) let scrollPercentage = self.scrollPercentage() if (scrollPercentage > 0){ - var fromIndex = self.currentIndex - var toIndex = self.currentIndex - let scrollDirection = self.scrollDirection() + var fromIndex = currentIndex + var toIndex = currentIndex + let direction = swipeDirection() - if (scrollDirection == .Left){ - if (virtualPage > self.getPagerTabStripChildViewControllersForScrolling()!.count - 1){ + if direction == .Left { + if virtualPage > self.getPagerTabStripChildViewControllersForScrolling()!.count - 1{ fromIndex = self.getPagerTabStripChildViewControllersForScrolling()!.count - 1 toIndex = self.getPagerTabStripChildViewControllersForScrolling()!.count } - else{ + else { if (scrollPercentage >= 0.5){ fromIndex = max(toIndex - 1, 0) } @@ -341,7 +327,7 @@ public class XLPagerTabStripViewController: UIViewController, UIScrollViewDelega } } } - else if (scrollDirection == .Right){ + else if direction == .Right { if (virtualPage < 0){ fromIndex = 0 toIndex = -1 @@ -355,29 +341,27 @@ public class XLPagerTabStripViewController: UIViewController, UIScrollViewDelega } } } - self.delegate?.pagerTabStripViewController(self, updateIndicatorFromIndex: fromIndex, toIndex: toIndex, withProgressPercentage: (self.isElasticIndicatorLimit ? scrollPercentage : (toIndex < 0 || toIndex >= self.getPagerTabStripChildViewControllersForScrolling()!.count ? 0 : scrollPercentage)), indexWasChanged: changeCurrentIndex) + try! self.delegate?.pagerTabStripViewController(self, updateIndicatorFromIndex: fromIndex, toIndex: toIndex, withProgressPercentage: (self.isElasticIndicatorLimit ? scrollPercentage : (toIndex < 0 || toIndex >= self.getPagerTabStripChildViewControllersForScrolling()!.count ? 0 : scrollPercentage)), indexWasChanged: changeCurrentIndex) } } else{ - self.delegate?.pagerTabStripViewController(self, updateIndicatorFromIndex: min(oldCurrentIndex, self.getPagerTabStripChildViewControllersForScrolling()!.count - 1), toIndex: newCurrentIndex) + try! self.delegate?.pagerTabStripViewController(self, updateIndicatorFromIndex: min(oldCurrentIndex, self.getPagerTabStripChildViewControllersForScrolling()!.count - 1), toIndex: newCurrentIndex) } } - public func reloadPagerTabStripView() - { - if (self.isViewLoaded()){ - for item in self.pagerTabStripChildViewControllers!.enumerate(){ - let childController = item.element - if (childController.parentViewController != nil){ + public func reloadPagerTabStripView(){ + if isViewLoaded() { + for childController in pagerTabStripChildViewControllers { + if childController.parentViewController != nil { childController.view.removeFromSuperview() childController.willMoveToParentViewController(nil) childController.removeFromParentViewController() } } - pagerTabStripChildViewControllers = (self.datasource != nil) ? self.datasource?.childViewControllersForPagerTabStripViewController(self) : [] + pagerTabStripChildViewControllers = datasource? .childViewControllersForPagerTabStripViewController(self) ?? [] self.containerView?.contentSize = CGSizeMake(CGRectGetWidth(self.containerView!.bounds) * CGFloat(self.pagerTabStripChildViewControllers!.count), self.containerView!.contentSize.height) - if (currentIndex >= self.pagerTabStripChildViewControllers!.count){ + if currentIndex >= pagerTabStripChildViewControllers.count { currentIndex = pagerTabStripChildViewControllers!.count - 1 } self.containerView?.contentOffset = CGPointMake(self.pageOffsetForChildIndex(index: currentIndex), 0) @@ -395,8 +379,8 @@ public class XLPagerTabStripViewController: UIViewController, UIScrollViewDelega public func scrollViewWillBeginDragging(scrollView: UIScrollView) { if (self.containerView == scrollView){ - lastPageNumber = self.pageForContentOffset(contentOffset: Float(scrollView.contentOffset.x)) - lastContentOffset = Float(scrollView.contentOffset.x) + lastPageNumber = pageForContentOffset(contentOffset: Float(scrollView.contentOffset.x)) + lastContentOffset = scrollView.contentOffset.x } } diff --git a/Sources/SegmentedPagerTabStripViewController.swift b/Sources/SegmentedPagerTabStripViewController.swift new file mode 100644 index 0000000..3ddde7b --- /dev/null +++ b/Sources/SegmentedPagerTabStripViewController.swift @@ -0,0 +1,123 @@ +// SegmentedPagerTabStripViewController.swift +// XLPagerTabStrip ( https://github.com/xmartlabs/XLPagerTabStrip ) +// +// Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com ) +// +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + + +public class SegmentedPagerTabStripViewController: PagerTabStripViewController { + + @IBOutlet lazy public var segmentedControl: UISegmentedControl! = UISegmentedControl() + + var shouldUpdateSegmentedControl = true + + public override func viewDidLoad() { + super.viewDidLoad() + if segmentedControl.superview == nil { + navigationItem.titleView = segmentedControl + } + segmentedControl.addTarget(self, action: "segmentedControlChanged:", forControlEvents: .ValueChanged) + } + + public override func reloadPagerTabStripView() { + super.reloadPagerTabStripView() + if isViewLoaded() { + try! reloadSegmentedControl() + } + } + + func reloadSegmentedControl() throws -> Void { + segmentedControl.removeAllSegments() + guard let pagerTabStripChildViewControllers = pagerTabStripChildViewControllers where pagerTabStripChildViewControllers.count > 0 else { + throw PagerTabStripError.PagerTabStripChildViewControllersMustContainAtLeastOneViewController + } + for (index, item) in pagerTabStripChildViewControllers.enumerate(){ + guard let child = item as? PagerTabStripChildItem else { + throw PagerTabStripError.ChildViewControllerMustConformToPagerTabStripChildItem + } + if let image = child.childHeaderForPagerTabStripViewController(self).image { + segmentedControl.insertSegmentWithImage(image, atIndex: index, animated: false) + } + else { + segmentedControl.insertSegmentWithTitle(child.childHeaderForPagerTabStripViewController(self).title, atIndex: index, animated: false) + } + } + + guard let child = pagerTabStripChildViewControllers[currentIndex] as? PagerTabStripChildItem else { + throw PagerTabStripError.CurrentIndexIsGreaterThanChildsCount + } + segmentedControl.selectedSegmentIndex = currentIndex + if let color = child.childHeaderForPagerTabStripViewController(self).color { + segmentedControl.tintColor = color + } + } + + func segmentedControlChanged(sender: UISegmentedControl) -> Void{ + let index = sender.selectedSegmentIndex + shouldUpdateSegmentedControl = true + try! pagerTabStripViewController(self, updateIndicatorFromIndex: currentIndex, toIndex: index) + shouldUpdateSegmentedControl = false + moveToViewControllerAtIndex(index) + } + + // MARK: - PagerTabStripViewControllerDelegate + + override public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws { + try super.pagerTabStripViewController(pagerTabStripViewController, updateIndicatorFromIndex: fromIndex, toIndex: toIndex) + if shouldUpdateSegmentedControl { + guard let pagerTabStripChildViewControllers = pagerTabStripChildViewControllers where pagerTabStripChildViewControllers.count > 0 else { + throw PagerTabStripError.PagerTabStripChildViewControllersMustContainAtLeastOneViewController + } + guard let child = pagerTabStripChildViewControllers[toIndex] as? PagerTabStripChildItem else { + throw PagerTabStripError.CurrentIndexIsGreaterThanChildsCount + } + if let color = child.childHeaderForPagerTabStripViewController(self).color{ + segmentedControl.tintColor = color + } + segmentedControl.selectedSegmentIndex = toIndex + } + } + + public override func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex index: Int, withProgressPercentage progressPercentage: Float, indexWasChanged changed: Bool) throws { + if shouldUpdateSegmentedControl{ + guard let pagerTabStripChildViewControllers = pagerTabStripChildViewControllers where pagerTabStripChildViewControllers.count > 0 else { + throw PagerTabStripError.PagerTabStripChildViewControllersMustContainAtLeastOneViewController + } + let currentIndex = (progressPercentage > 0.5) ? index : fromIndex + guard let child = pagerTabStripChildViewControllers[currentIndex] as? PagerTabStripChildItem else { + throw PagerTabStripError.CurrentIndexIsGreaterThanChildsCount + } + if let color = child.childHeaderForPagerTabStripViewController(self).color{ + segmentedControl.tintColor = color + } + segmentedControl.selectedSegmentIndex = min(currentIndex, pagerTabStripChildViewControllers.count - 1) + } + } + + // MARK: - UIScrollViewDelegate + + public override func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) { + super.scrollViewDidEndScrollingAnimation(scrollView) + shouldUpdateSegmentedControl = true + } +} diff --git a/Sources/XLSegmentedPagerTabStripViewController.swift b/Sources/XLSegmentedPagerTabStripViewController.swift deleted file mode 100644 index 1785058..0000000 --- a/Sources/XLSegmentedPagerTabStripViewController.swift +++ /dev/null @@ -1,104 +0,0 @@ -// -// XLSegmentedPagerTabStripViewController.swift -// XLPagerTabStrip -// -// Created by Santiago on 1/19/16. -// -// - -import Foundation - -public class XLSegmentedPagerTabStripViewController : XLPagerTabStripViewController{ - var segmentedControl : UISegmentedControl - var shouldUpdateSegmentedControl : Bool - - required public init?(coder aDecoder: NSCoder) { - segmentedControl = UISegmentedControl() - shouldUpdateSegmentedControl = true - super.init(coder: aDecoder) - } - - override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { - segmentedControl = UISegmentedControl() - shouldUpdateSegmentedControl = true - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - } - - public override func viewDidLoad() { - super.viewDidLoad() - - if segmentedControl.superview != nil{ - navigationItem.titleView = segmentedControl - } - - segmentedControl.addTarget(self, action: "segmentedControlChanged:", forControlEvents: .ValueChanged) - } - - public override func reloadPagerTabStripView() { - super.reloadPagerTabStripView() - if (isViewLoaded()){ - reloadSegmentedControl() - } - } - - func reloadSegmentedControl() -> Void{ - segmentedControl.removeAllSegments() - for (index, item) in pagerTabStripChildViewControllers!.enumerate(){ - - let child = item as! XLPagerTabStripChildItem - - if let image = child.childHeaderForPagerTabStripViewController(self).image{ - segmentedControl.insertSegmentWithImage(image, atIndex: index, animated: false) - } - else{ - segmentedControl.insertSegmentWithTitle(child.childHeaderForPagerTabStripViewController(self).title, atIndex: index, animated: false) - } - } - - let child : XLPagerTabStripChildItem = pagerTabStripChildViewControllers![currentIndex] as! XLPagerTabStripChildItem - - segmentedControl.selectedSegmentIndex = currentIndex - - if let color = child.childHeaderForPagerTabStripViewController(self).color{ - segmentedControl.tintColor = color - } - } - - func segmentedControlChanged(sender: UISegmentedControl) -> Void{ - let index = sender.selectedSegmentIndex - pagerTabStripViewController(self, updateIndicatorFromIndex: 0, toIndex: index) - shouldUpdateSegmentedControl = false - moveToViewControllerAtIndex(index) - } - - // MARK: - XLPagerTabStripViewControllerDelegate - - override public func pagerTabStripViewController(pagerTabStripViewController: XLPagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex index: Int) { - if shouldUpdateSegmentedControl{ - let child = pagerTabStripChildViewControllers![index] as! XLPagerTabStripChildItem - if let color = child.childHeaderForPagerTabStripViewController(self).color{ - segmentedControl.tintColor = color - } - segmentedControl.selectedSegmentIndex = pagerTabStripChildViewControllers!.indexOf(pagerTabStripChildViewControllers![index])! - } - } - - public override func pagerTabStripViewController(pagerTabStripViewController: XLPagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex index: Int, withProgressPercentage progressPercentage: Float, indexWasChanged changed: Bool) { - if shouldUpdateSegmentedControl{ - let currentIndex = (progressPercentage > 0.5) ? index : fromIndex - let child = pagerTabStripChildViewControllers![currentIndex] as! XLPagerTabStripChildItem - if let color = child.childHeaderForPagerTabStripViewController(self).color{ - segmentedControl.tintColor = color - } - segmentedControl.selectedSegmentIndex = min(max(0, currentIndex), pagerTabStripChildViewControllers!.count - 1) - - } - } - - // MARK: - UIScrollViewDelegate - - public override func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) { - super.scrollViewDidEndScrollingAnimation(scrollView) - shouldUpdateSegmentedControl = true - } -} \ No newline at end of file diff --git a/XLPagerTabStrip.xcodeproj/project.pbxproj b/XLPagerTabStrip.xcodeproj/project.pbxproj index 2f1d6ca..2fe6c34 100644 --- a/XLPagerTabStrip.xcodeproj/project.pbxproj +++ b/XLPagerTabStrip.xcodeproj/project.pbxproj @@ -8,10 +8,12 @@ /* Begin PBXBuildFile section */ 287D0A6E1C4B73BD004566D6 /* XLPagerTabStripTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287D0A6D1C4B73BD004566D6 /* XLPagerTabStripTests.swift */; }; + 28E098BE1C5002D90083B788 /* PagerTabStripError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28E098BD1C5002D90083B788 /* PagerTabStripError.swift */; }; + 28E098C01C5003130083B788 /* PagerTabStripSwipeDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28E098BF1C5003130083B788 /* PagerTabStripSwipeDirection.swift */; }; 28F828811C494B2C00330CF4 /* XLPagerTabStrip.h in Headers */ = {isa = PBXBuildFile; fileRef = 28F828801C494B2C00330CF4 /* XLPagerTabStrip.h */; settings = {ATTRIBUTES = (Public, ); }; }; 28F828881C494B2C00330CF4 /* XLPagerTabStrip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28F8287D1C494B2C00330CF4 /* XLPagerTabStrip.framework */; }; - CB71C6EE1C4EB988008EC806 /* XLSegmentedPagerTabStripViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB71C6ED1C4EB988008EC806 /* XLSegmentedPagerTabStripViewController.swift */; }; - CB86ED6B1C4D6E6C00DA463B /* XLPagerTabStripViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB86ED6A1C4D6E6C00DA463B /* XLPagerTabStripViewController.swift */; }; + CB71C6EE1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB71C6ED1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift */; }; + CB86ED6B1C4D6E6C00DA463B /* PagerTabStripViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB86ED6A1C4D6E6C00DA463B /* PagerTabStripViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -26,14 +28,16 @@ /* Begin PBXFileReference section */ 287D0A6D1C4B73BD004566D6 /* XLPagerTabStripTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = XLPagerTabStripTests.swift; path = Tests/XLPagerTabStripTests.swift; sourceTree = SOURCE_ROOT; }; + 28E098BD1C5002D90083B788 /* PagerTabStripError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagerTabStripError.swift; sourceTree = ""; }; + 28E098BF1C5003130083B788 /* PagerTabStripSwipeDirection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagerTabStripSwipeDirection.swift; sourceTree = ""; }; 28F8287D1C494B2C00330CF4 /* XLPagerTabStrip.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XLPagerTabStrip.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 28F828801C494B2C00330CF4 /* XLPagerTabStrip.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XLPagerTabStrip.h; sourceTree = ""; }; 28F828821C494B2C00330CF4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28F828871C494B2C00330CF4 /* XLPagerTabStripTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XLPagerTabStripTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 28F8288E1C494B2C00330CF4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = Info.plist; path = Tests/Info.plist; sourceTree = ""; }; 28F8289B1C494BF100330CF4 /* Playground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Playground.playground; sourceTree = ""; }; - CB71C6ED1C4EB988008EC806 /* XLSegmentedPagerTabStripViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XLSegmentedPagerTabStripViewController.swift; sourceTree = ""; }; - CB86ED6A1C4D6E6C00DA463B /* XLPagerTabStripViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XLPagerTabStripViewController.swift; sourceTree = ""; }; + CB71C6ED1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedPagerTabStripViewController.swift; sourceTree = ""; }; + CB86ED6A1C4D6E6C00DA463B /* PagerTabStripViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagerTabStripViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -97,8 +101,10 @@ 28F828971C494B4200330CF4 /* Sources */ = { isa = PBXGroup; children = ( - CB86ED6A1C4D6E6C00DA463B /* XLPagerTabStripViewController.swift */, - CB71C6ED1C4EB988008EC806 /* XLSegmentedPagerTabStripViewController.swift */, + CB86ED6A1C4D6E6C00DA463B /* PagerTabStripViewController.swift */, + CB71C6ED1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift */, + 28E098BD1C5002D90083B788 /* PagerTabStripError.swift */, + 28E098BF1C5003130083B788 /* PagerTabStripSwipeDirection.swift */, ); path = Sources; sourceTree = ""; @@ -210,8 +216,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CB71C6EE1C4EB988008EC806 /* XLSegmentedPagerTabStripViewController.swift in Sources */, - CB86ED6B1C4D6E6C00DA463B /* XLPagerTabStripViewController.swift in Sources */, + CB71C6EE1C4EB988008EC806 /* SegmentedPagerTabStripViewController.swift in Sources */, + 28E098BE1C5002D90083B788 /* PagerTabStripError.swift in Sources */, + CB86ED6B1C4D6E6C00DA463B /* PagerTabStripViewController.swift in Sources */, + 28E098C01C5003130083B788 /* PagerTabStripSwipeDirection.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };