diff --git a/Example/Example/NavButtonBarExampleViewController.swift b/Example/Example/NavButtonBarExampleViewController.swift index 8ecdc6f..033c29e 100644 --- a/Example/Example/NavButtonBarExampleViewController.swift +++ b/Example/Example/NavButtonBarExampleViewController.swift @@ -24,7 +24,7 @@ public class NavButtonBarExampleViewController: ButtonBarPagerTabStripViewContro buttonBarView.removeFromSuperview() navigationController?.navigationBar.addSubview(buttonBarView) - changeCurrentIndexProgressive = { (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: Float, changeCurrentIndex: Bool, animated: Bool) -> Void in + changeCurrentIndexProgressive = { (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void in guard changeCurrentIndex == true else { return } oldCell?.label.textColor = UIColor(white: 1, alpha: 0.6) diff --git a/Sources/BarPagerTabStripViewController.swift b/Sources/BarPagerTabStripViewController.swift index 30e1dbe..2bac275 100644 --- a/Sources/BarPagerTabStripViewController.swift +++ b/Sources/BarPagerTabStripViewController.swift @@ -24,7 +24,7 @@ import Foundation -public class BarPagerTabStripViewController: PagerTabStripViewController { +public class BarPagerTabStripViewController: PagerTabStripViewController, PagerTabStripViewControllerDataSource, PagerTabStripViewControllerIsProgressiveDelegate { @IBOutlet lazy public var barView: BarView! = { [unowned self] in let barView = BarView(frame: CGRectMake(0, 0, self.view.frame.size.width, 5.0)) @@ -34,6 +34,18 @@ public class BarPagerTabStripViewController: PagerTabStripViewController { return barView }() + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + delegate = self + datasource = self + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + delegate = self + datasource = self + } + public override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) if barView.superview == nil { @@ -53,11 +65,11 @@ public class BarPagerTabStripViewController: PagerTabStripViewController { // MARK: - PagerTabStripViewControllerDelegate - public override func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws { + public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws { barView.moveToIndex(index: toIndex, animated: true) } - public override func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: Float, indexWasChanged: Bool) throws { + public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool) throws { barView.moveToIndex(fromIndex: fromIndex, toIndex: toIndex, progressPercentage: progressPercentage) } } diff --git a/Sources/BarView.swift b/Sources/BarView.swift index bcf8aa2..ba10ae6 100644 --- a/Sources/BarView.swift +++ b/Sources/BarView.swift @@ -72,7 +72,7 @@ public class BarView: UIView { updateSelectedBarPositionWithAnimation(animated) } - public func moveToIndex(fromIndex fromIndex: Int, toIndex: Int, progressPercentage: Float) { + public func moveToIndex(fromIndex fromIndex: Int, toIndex: Int, progressPercentage: CGFloat) { selectedIndex = (progressPercentage > 0.5) ? toIndex : fromIndex var newFrame = selectedBar.frame diff --git a/Sources/ButtonBarPagerTabStripViewController.swift b/Sources/ButtonBarPagerTabStripViewController.swift index b443dc3..2ebca14 100644 --- a/Sources/ButtonBarPagerTabStripViewController.swift +++ b/Sources/ButtonBarPagerTabStripViewController.swift @@ -24,10 +24,10 @@ import Foundation -public class ButtonBarPagerTabStripViewController: PagerTabStripViewController, UICollectionViewDelegate, UICollectionViewDataSource { +public class ButtonBarPagerTabStripViewController: PagerTabStripViewController, PagerTabStripViewControllerDataSource, PagerTabStripViewControllerIsProgressiveDelegate, UICollectionViewDelegate, UICollectionViewDataSource { public var changeCurrentIndex: ((oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, animated: Bool) -> Void)? = { _ in } - public var changeCurrentIndexProgressive: ((oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: Float, changeCurrentIndex: Bool, animated: Bool) -> Void)? = { _ in } + public var changeCurrentIndexProgressive: ((oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void)? = { _ in } @IBOutlet public lazy var buttonBarView: ButtonBarView! = { [unowned self] in var flowLayout = UICollectionViewFlowLayout() @@ -62,10 +62,14 @@ public class ButtonBarPagerTabStripViewController: PagerTabStripViewController, override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + delegate = self + datasource = self } required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) + delegate = self + datasource = self } public override func viewDidLoad() { @@ -125,11 +129,6 @@ public class ButtonBarPagerTabStripViewController: PagerTabStripViewController, } } - public override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) { - super.willRotateToInterfaceOrientation(toInterfaceOrientation, duration: duration) - isViewRotating = true - } - // MARK: - Public Methods public override func reloadPagerTabStripView() { @@ -167,7 +166,7 @@ public class ButtonBarPagerTabStripViewController: PagerTabStripViewController, return calculateStretchedCellWidths(minimumCellWidths, suggestedStretchedCellWidth: newSuggestedStretchedCellWidth, previousNumberOfLargeCells: numberOfLargeCells) } - public override func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws { + public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws { guard shouldUpdateButtonBarView else { return } let direction: SwipeDirection = (toIndex < fromIndex) ? .Right : .Left @@ -179,7 +178,7 @@ public class ButtonBarPagerTabStripViewController: PagerTabStripViewController, } } - public override func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: Float, indexWasChanged: Bool) throws { + public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool) throws { guard shouldUpdateButtonBarView else { return } buttonBarView.moveFromIndex(fromIndex, toIndex: toIndex, progressPercentage: progressPercentage, pagerScroll: .YES) diff --git a/Sources/ButtonBarView.swift b/Sources/ButtonBarView.swift index 0163b9e..8a17ed4 100644 --- a/Sources/ButtonBarView.swift +++ b/Sources/ButtonBarView.swift @@ -63,7 +63,7 @@ public class ButtonBarView: UICollectionView { updateSelectedBarPosition(animated, swipeDirection: swipeDirection, pagerScroll: pagerScroll) } - public func moveFromIndex(fromIndex: Int, toIndex: Int, progressPercentage: Float,pagerScroll: PagerScroll) -> Void { + public func moveFromIndex(fromIndex: Int, toIndex: Int, progressPercentage: CGFloat,pagerScroll: PagerScroll) -> Void { selectedIndex = (progressPercentage > 0.5) ? toIndex : fromIndex let fromFrame = layoutAttributesForItemAtIndexPath(NSIndexPath(forItem: fromIndex, inSection: 0))!.frame @@ -86,8 +86,8 @@ public class ButtonBarView: UICollectionView { var targetFrame = fromFrame targetFrame.size.height = selectedBar.frame.size.height - targetFrame.size.width += (toFrame.size.width - fromFrame.size.width) * CGFloat(progressPercentage) - targetFrame.origin.x += (toFrame.origin.x - fromFrame.origin.x) * CGFloat(progressPercentage) + targetFrame.size.width += (toFrame.size.width - fromFrame.size.width) * progressPercentage + targetFrame.origin.x += (toFrame.origin.x - fromFrame.origin.x) * progressPercentage selectedBar.frame = CGRectMake(targetFrame.origin.x, selectedBar.frame.origin.y, targetFrame.size.width, selectedBar.frame.size.height) @@ -96,7 +96,7 @@ public class ButtonBarView: UICollectionView { let toContentOffset = contentOffsetForCell(withFrame: toFrame, andIndex: toIndex) let fromContentOffset = contentOffsetForCell(withFrame: fromFrame, andIndex: fromIndex) - targetContentOffset = fromContentOffset + ((toContentOffset - fromContentOffset) * CGFloat(progressPercentage)) + targetContentOffset = fromContentOffset + ((toContentOffset - fromContentOffset) * progressPercentage) } let animated = abs(contentOffset.x - targetContentOffset) > 30 || (fromIndex == toIndex) diff --git a/Sources/PagerTabStripViewController.swift b/Sources/PagerTabStripViewController.swift index 12b3f5f..595761b 100644 --- a/Sources/PagerTabStripViewController.swift +++ b/Sources/PagerTabStripViewController.swift @@ -36,8 +36,12 @@ public protocol PagerTabStripChildItem { 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 PagerTabStripViewControllerIsProgressiveDelegate : PagerTabStripViewControllerDelegate { + + func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool) throws } public protocol PagerTabStripViewControllerDataSource: class { @@ -48,8 +52,7 @@ public protocol PagerTabStripViewControllerDataSource: class { //MARK: PagerTabStripViewController -public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate, PagerTabStripViewControllerDataSource, PagerTabStripViewControllerDelegate { - +public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate { @IBOutlet lazy public var containerView: UIScrollView! = { [unowned self] in let containerView = UIScrollView(frame: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds))) @@ -69,22 +72,28 @@ public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate return CGRectGetWidth(containerView.bounds) } - override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - delegate = self - datasource = self + public var scrollPercentage: CGFloat { + if swipeDirection != .Right { + let module = fmod(containerView.contentOffset.x, pageWidth) + return module == 0.0 ? 1.0 : module / pageWidth + } + return 1 - fmod(containerView.contentOffset.x >= 0 ? containerView.contentOffset.x : pageWidth + containerView.contentOffset.x, pageWidth) / pageWidth } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - delegate = self - datasource = self + + public var swipeDirection: SwipeDirection { + if containerView.contentOffset.x > lastContentOffset { + return .Left + } + else if containerView.contentOffset.x < lastContentOffset { + return .Right + } + return .None } override public func viewDidLoad() { super.viewDidLoad() if containerView.superview == nil { - view.addSubview(containerView!) + view.addSubview(containerView) } containerView.bounces = true containerView.alwaysBounceHorizontal = true @@ -97,16 +106,15 @@ public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate guard let dataSource = datasource else { fatalError("dataSource must not be nil") } - let childViewControllers = dataSource.childViewControllersForPagerTabStripViewController(self) - guard childViewControllers.count != 0 else { + viewControllers = dataSource.childViewControllersForPagerTabStripViewController(self) + guard viewControllers.count != 0 else { fatalError("childViewControllersForPagerTabStripViewController should provide at least one child view controller") } - viewControllers = childViewControllers } override public func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) - lastSize = containerView!.bounds.size + lastSize = containerView.bounds.size updateIfNeeded() } @@ -120,17 +128,18 @@ public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate } public func moveToViewControllerAtIndex(index: Int, animated: Bool) { - if !isViewLoaded() || view.window == nil { + guard isViewLoaded() && view.window != nil else { currentIndex = index + return } if animated && pagerOptions.contains(.SkipIntermediateViewControllers) && abs(currentIndex - index) > 1 { - var tmpChildViewControllers = viewControllers + var tmpViewControllers = viewControllers let currentChildVC = viewControllers[currentIndex] let fromIndex = currentIndex < index ? index - 1 : index + 1 let fromChildVC = viewControllers[fromIndex] - tmpChildViewControllers[currentIndex] = fromChildVC - tmpChildViewControllers[fromIndex] = currentChildVC - pagerTabStripChildViewControllersForScrolling = tmpChildViewControllers + tmpViewControllers[currentIndex] = fromChildVC + tmpViewControllers[fromIndex] = currentChildVC + pagerTabStripChildViewControllersForScrolling = tmpViewControllers containerView.setContentOffset(CGPointMake(pageOffsetForChildIndex(index: fromIndex), 0), animated: false) (navigationController?.view ?? view).userInteractionEnabled = false containerView.setContentOffset(CGPointMake(pageOffsetForChildIndex(index: index), 0), animated: true) @@ -155,41 +164,23 @@ public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate return [] } - //MARK: - PagerTabStripViewControllerDelegate - - public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws { - } - - public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: Float, indexWasChanged: Bool) throws { - } - //MARK: - Helpers public func updateIfNeeded() { - if !CGSizeEqualToSize(lastSize, containerView!.bounds.size){ + if !CGSizeEqualToSize(lastSize, containerView.bounds.size){ updateContent() } } - public func swipeDirection() -> SwipeDirection { - if containerView.contentOffset.x > lastContentOffset { - return .Left - } - else if containerView.contentOffset.x < lastContentOffset { - return .Right - } - return .None - } - - public func canMoveToIndex(index index: Int) -> Bool{ + public func canMoveToIndex(index index: Int) -> Bool { return currentIndex != index && viewControllers.count > index } - public func pageOffsetForChildIndex(index index: Int) -> CGFloat{ + public func pageOffsetForChildIndex(index index: Int) -> CGFloat { return CGFloat(index) * CGRectGetWidth(containerView.bounds) } - public func offsetForChildIndex(index index: Int) -> CGFloat{ + public func offsetForChildIndex(index: Int) -> CGFloat{ return (CGFloat(index) * CGRectGetWidth(containerView.bounds)) + ((CGRectGetWidth(containerView.bounds) - CGRectGetWidth(view.bounds)) * 0.5) } @@ -197,71 +188,54 @@ public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate guard let index = viewControllers.indexOf(viewController) else { throw PagerTabStripError.ViewControllerNotContainedInPagerTabStripChildViewControllers } - return offsetForChildIndex(index: index) + return offsetForChildIndex(index) } - public func pageForContentOffset(contentOffset contentOffset: CGFloat) -> Int{ - let result = self.virtualPageForContentOffset(contentOffset: contentOffset) - return self.pageForVirtualPage(virtualPage: result) + public func pageForContentOffset(contentOffset: CGFloat) -> Int { + let result = virtualPageForContentOffset(contentOffset) + return pageForVirtualPage(result) } - public func virtualPageForContentOffset(contentOffset contentOffset: CGFloat) -> Int{ + public func virtualPageForContentOffset(contentOffset: CGFloat) -> Int { return Int((contentOffset + 1.5 * pageWidth) / pageWidth) - 1 } - public func pageForVirtualPage(virtualPage virtualPage: Int) -> Int{ + public func pageForVirtualPage(virtualPage: Int) -> Int{ if virtualPage < 0 { return 0 } - if virtualPage > viewControllers.count - 1 { return viewControllers.count - 1 } + if virtualPage > viewControllers.count - 1 { + return viewControllers.count - 1 + } return virtualPage } - public func scrollPercentage() -> CGFloat{ - if swipeDirection() != .Right { - if fmod(containerView.contentOffset.x, pageWidth) == 0.0{ - return 1.0 - } - return fmod(containerView.contentOffset.x, pageWidth) / pageWidth - } - return 1 - fmod(containerView.contentOffset.x >= 0 ? containerView!.contentOffset.x : pageWidth + containerView.contentOffset.x, pageWidth) / pageWidth; - } - public func updateContent() { - if !CGSizeEqualToSize(lastSize, containerView.bounds.size) { - if lastSize.width != containerView.bounds.size.width { - lastSize = containerView.bounds.size - containerView.contentOffset = CGPointMake(pageOffsetForChildIndex(index: currentIndex), 0) - } - else { - lastSize = containerView.bounds.size - } + if lastSize.width != containerView.bounds.size.width { + lastSize = containerView.bounds.size + containerView.contentOffset = CGPointMake(pageOffsetForChildIndex(index: currentIndex), 0) } + lastSize = containerView.bounds.size - let childViewControllers = getPagerTabStripChildViewControllersForScrolling - containerView.contentSize = CGSizeMake(CGRectGetWidth(containerView.bounds) * CGFloat(childViewControllers.count), containerView.contentSize.height) + let pagerViewControllers = pagerTabStripChildViewControllersForScrolling ?? viewControllers + containerView.contentSize = CGSizeMake(CGRectGetWidth(containerView.bounds) * CGFloat(pagerViewControllers.count), containerView.contentSize.height) - for (index, childController) in childViewControllers.enumerate(){ + for (index, childController) in pagerViewControllers.enumerate() { let pageOffsetForChild = pageOffsetForChildIndex(index: index) if fabs(containerView.contentOffset.x - pageOffsetForChild) < CGRectGetWidth(containerView.bounds) { - if childController.parentViewController == nil { + if let _ = childController.parentViewController { + childController.view.frame = CGRectMake(offsetForChildIndex(index), 0, CGRectGetWidth(view.bounds), CGRectGetHeight(containerView.bounds)) + childController.view.autoresizingMask = [.FlexibleHeight, .FlexibleWidth] + } + else { addChildViewController(childController) childController.beginAppearanceTransition(true, animated: false) - - let childPosition = offsetForChildIndex(index: index) - childController.view.frame = CGRectMake(childPosition, 0, CGRectGetWidth(view.bounds), CGRectGetHeight(containerView.bounds)) + childController.view.frame = CGRectMake(offsetForChildIndex(index), 0, CGRectGetWidth(view.bounds), CGRectGetHeight(containerView.bounds)) childController.view.autoresizingMask = [.FlexibleHeight, .FlexibleWidth] - containerView.addSubview(childController.view) childController.didMoveToParentViewController(self) childController.endAppearanceTransition() } - else { - let childPosition = offsetForChildIndex(index: index) - childController.view.frame = CGRectMake(childPosition, 0, CGRectGetWidth(view.bounds), CGRectGetHeight(containerView.bounds)) - childController.view.autoresizingMask = [.FlexibleHeight, .FlexibleWidth] - - } } else { if let _ = childController.parentViewController { @@ -275,75 +249,37 @@ public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate } let oldCurrentIndex = currentIndex - let virtualPage = virtualPageForContentOffset(contentOffset: containerView.contentOffset.x) - let newCurrentIndex = pageForVirtualPage(virtualPage: virtualPage) + let virtualPage = virtualPageForContentOffset(containerView.contentOffset.x) + let newCurrentIndex = pageForVirtualPage(virtualPage) currentIndex = newCurrentIndex let changeCurrentIndex = newCurrentIndex != oldCurrentIndex - if pagerOptions.contains(.IsProgressiveIndicator) { - // FIXME: - check if delegate implements? pagerTabStripViewController(pagerTabStripViewController: XLPagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex index: Int, withProgressPercentage progressPercentage: Float, indexWasChanged changed: Bool) + if let progressiveDeledate = self as? PagerTabStripViewControllerIsProgressiveDelegate where pagerOptions.contains(.IsProgressiveIndicator) { - let scrollPercentage = self.scrollPercentage() - if scrollPercentage > 0 { - var fromIndex = currentIndex - var toIndex = currentIndex - let direction = swipeDirection() - - if direction == .Left { - if virtualPage > getPagerTabStripChildViewControllersForScrolling.count - 1 { - fromIndex = getPagerTabStripChildViewControllersForScrolling.count - 1 - toIndex = getPagerTabStripChildViewControllersForScrolling.count - } - else { - if scrollPercentage >= 0.5 { - fromIndex = max(toIndex - 1, 0) - } - else { - toIndex = fromIndex + 1 - } - } - } - else if direction == .Right { - if virtualPage < 0 { - fromIndex = 0 - toIndex = -1 - } - else { - if scrollPercentage > 0.5 { - fromIndex = min(toIndex + 1, getPagerTabStripChildViewControllersForScrolling.count - 1) - } - else { - toIndex = fromIndex - 1 - } - } - } - - try! delegate?.pagerTabStripViewController(self, updateIndicatorFromIndex: fromIndex, toIndex: toIndex, withProgressPercentage: Float(pagerOptions.contains(.IsElasticIndicatorLimit) ? scrollPercentage : (toIndex < 0 || toIndex >= getPagerTabStripChildViewControllersForScrolling.count ? CGFloat(0) : scrollPercentage)), indexWasChanged: changeCurrentIndex) - } + let (fromIndex, toIndex, scrollPercentage) = progressiveIndicatorData(virtualPage) + try! progressiveDeledate.pagerTabStripViewController(self, updateIndicatorFromIndex: fromIndex, toIndex: toIndex, withProgressPercentage: scrollPercentage, indexWasChanged: changeCurrentIndex) } else{ - try! delegate?.pagerTabStripViewController(self, updateIndicatorFromIndex: min(oldCurrentIndex, getPagerTabStripChildViewControllersForScrolling.count - 1), toIndex: newCurrentIndex) + try! delegate?.pagerTabStripViewController(self, updateIndicatorFromIndex: min(oldCurrentIndex, pagerViewControllers.count - 1), toIndex: newCurrentIndex) } } - + public func reloadPagerTabStripView() { - if isViewLoaded() { - for childController in viewControllers { - if let _ = childController.parentViewController { - childController.view.removeFromSuperview() - childController.willMoveToParentViewController(nil) - childController.removeFromParentViewController() - } + guard isViewLoaded() else { return } + for childController in viewControllers { + if let _ = childController.parentViewController { + childController.view.removeFromSuperview() + childController.willMoveToParentViewController(nil) + childController.removeFromParentViewController() } - - viewControllers = datasource?.childViewControllersForPagerTabStripViewController(self) ?? [] - containerView.contentSize = CGSizeMake(CGRectGetWidth(containerView.bounds) * CGFloat(viewControllers.count), containerView.contentSize.height) - if currentIndex >= viewControllers.count { - currentIndex = viewControllers.count - 1 - } - containerView.contentOffset = CGPointMake(pageOffsetForChildIndex(index: currentIndex), 0) - updateContent() } + viewControllers = datasource?.childViewControllersForPagerTabStripViewController(self) ?? [] + containerView.contentSize = CGSizeMake(CGRectGetWidth(containerView.bounds) * CGFloat(viewControllers.count), containerView.contentSize.height) + if currentIndex >= viewControllers.count { + currentIndex = viewControllers.count - 1 + } + containerView.contentOffset = CGPointMake(pageOffsetForChildIndex(index: currentIndex), 0) + updateContent() } //MARK: - UIScrollDelegate @@ -356,7 +292,7 @@ public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate public func scrollViewWillBeginDragging(scrollView: UIScrollView) { if containerView == scrollView { - lastPageNumber = pageForContentOffset(contentOffset: scrollView.contentOffset.x) + lastPageNumber = pageForContentOffset(scrollView.contentOffset.x) lastContentOffset = scrollView.contentOffset.x } } @@ -364,12 +300,7 @@ public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate public func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) { if containerView == scrollView { pagerTabStripChildViewControllersForScrolling = nil - if let navigationController = navigationController { - navigationController.view.userInteractionEnabled = true - } - else{ - view.userInteractionEnabled = true - } + (navigationController?.view ?? view).userInteractionEnabled = true updateContent() } } @@ -379,21 +310,55 @@ public class PagerTabStripViewController: UIViewController, UIScrollViewDelegate public override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) pageBeforeRotate = currentIndex - coordinator.animateAlongsideTransition(nil) { (context) -> Void in - self.currentIndex = self.pageBeforeRotate - self.updateIfNeeded() + coordinator.animateAlongsideTransition(nil) { [weak self] _ in + guard let me = self else { return } + me.currentIndex = me.pageBeforeRotate + me.updateIfNeeded() } } - public override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) { - pageBeforeRotate = currentIndex - } + //MARK: Private + + private func progressiveIndicatorData(virtualPage: Int) -> (Int, Int, CGFloat) { + let count = viewControllers.count + var fromIndex = currentIndex + var toIndex = currentIndex + let direction = swipeDirection + + if direction == .Left { + if virtualPage > count - 1 { + fromIndex = count - 1 + toIndex = count + } + else { + if self.scrollPercentage >= 0.5 { + fromIndex = max(toIndex - 1, 0) + } + else { + toIndex = fromIndex + 1 + } + } + } + else if direction == .Right { + if virtualPage < 0 { + fromIndex = 0 + toIndex = -1 + } + else { + if self.scrollPercentage > 0.5 { + fromIndex = min(toIndex + 1, count - 1) + } + else { + toIndex = fromIndex - 1 + } + } + } + let scrollPercentage = pagerOptions.contains(.IsElasticIndicatorLimit) ? self.scrollPercentage : ((toIndex < 0 || toIndex >= count) ? 0.0 : self.scrollPercentage) + return (fromIndex, toIndex, scrollPercentage) + } private var pagerTabStripChildViewControllersForScrolling : [UIViewController]? - private var getPagerTabStripChildViewControllersForScrolling : [UIViewController] { - return pagerTabStripChildViewControllersForScrolling ?? viewControllers - } private var lastPageNumber = 0 private var lastContentOffset: CGFloat = 0.0 private var pageBeforeRotate = 0 diff --git a/Sources/SegmentedPagerTabStripViewController.swift b/Sources/SegmentedPagerTabStripViewController.swift index e6b3d9f..53d510a 100644 --- a/Sources/SegmentedPagerTabStripViewController.swift +++ b/Sources/SegmentedPagerTabStripViewController.swift @@ -25,10 +25,22 @@ import Foundation -public class SegmentedPagerTabStripViewController: PagerTabStripViewController { +public class SegmentedPagerTabStripViewController: PagerTabStripViewController, PagerTabStripViewControllerDataSource, PagerTabStripViewControllerDelegate { @IBOutlet lazy public var segmentedControl: UISegmentedControl! = UISegmentedControl() + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + delegate = self + datasource = self + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + delegate = self + datasource = self + } + var shouldUpdateSegmentedControl = true public override func viewDidLoad() { @@ -47,7 +59,7 @@ public class SegmentedPagerTabStripViewController: PagerTabStripViewController { } } - func reloadSegmentedControl() throws -> Void { + func reloadSegmentedControl() throws { segmentedControl.removeAllSegments() for (index, item) in viewControllers.enumerate(){ guard let child = item as? PagerTabStripChildItem else { @@ -70,7 +82,7 @@ public class SegmentedPagerTabStripViewController: PagerTabStripViewController { } } - func segmentedControlChanged(sender: UISegmentedControl) -> Void{ + func segmentedControlChanged(sender: UISegmentedControl) { let index = sender.selectedSegmentIndex try! pagerTabStripViewController(self, updateIndicatorFromIndex: currentIndex, toIndex: index) shouldUpdateSegmentedControl = false @@ -79,32 +91,18 @@ public class SegmentedPagerTabStripViewController: PagerTabStripViewController { // MARK: - PagerTabStripViewControllerDelegate - override public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws { - try super.pagerTabStripViewController(pagerTabStripViewController, updateIndicatorFromIndex: fromIndex, toIndex: toIndex) - if shouldUpdateSegmentedControl { + public func pagerTabStripViewController(pagerTabStripViewController: PagerTabStripViewController, updateIndicatorFromIndex fromIndex: Int, toIndex: Int) throws { + if shouldUpdateSegmentedControl { guard let child = viewControllers[toIndex] as? PagerTabStripChildItem else { throw PagerTabStripError.CurrentIndexIsGreaterThanChildsCount } - if let color = child.childHeaderForPagerTabStripViewController(self).color{ + 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{ - let currentIndex = (progressPercentage > 0.5) ? index : fromIndex - guard let child = viewControllers[currentIndex] as? PagerTabStripChildItem else { - throw PagerTabStripError.CurrentIndexIsGreaterThanChildsCount - } - if let color = child.childHeaderForPagerTabStripViewController(self).color{ - segmentedControl.tintColor = color - } - segmentedControl.selectedSegmentIndex = min(currentIndex, viewControllers.count - 1) - } - } - // MARK: - UIScrollViewDelegate public override func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {