226 lines
9.6 KiB
Swift
226 lines
9.6 KiB
Swift
// TwitterPagerTabStripViewController.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 TwitterPagerTabStripViewController: PagerTabStripViewController, PagerTabStripViewControllerDataSource, PagerTabStripViewControllerIsProgressiveDelegate {
|
|
lazy var navigationView: UIView = {
|
|
let navigationView = UIView()
|
|
navigationView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
|
return navigationView
|
|
}()
|
|
|
|
lazy var navigationScrollView: UIScrollView = { [unowned self] in
|
|
let navigationScrollView = UIScrollView(frame: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 44))
|
|
navigationScrollView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
|
navigationScrollView.bounces = true
|
|
navigationScrollView.scrollsToTop = false
|
|
navigationScrollView.delegate = self
|
|
navigationScrollView.showsVerticalScrollIndicator = false
|
|
navigationScrollView.showsHorizontalScrollIndicator = false
|
|
navigationScrollView.pagingEnabled = true
|
|
navigationScrollView.userInteractionEnabled = false
|
|
navigationScrollView.alwaysBounceHorizontal = true
|
|
navigationScrollView.alwaysBounceVertical = false
|
|
return navigationScrollView
|
|
}()
|
|
var navigationPageControl: FXPageControl = {
|
|
let navigationPageControl = FXPageControl()
|
|
navigationPageControl.backgroundColor = .clearColor()
|
|
navigationPageControl.dotSize = 3.8
|
|
navigationPageControl.dotSpacing = 4.0
|
|
navigationPageControl.dotColor = UIColor(white: 1, alpha: 0.4)
|
|
navigationPageControl.selectedDotColor = .whiteColor()
|
|
navigationPageControl.userInteractionEnabled = false
|
|
return navigationPageControl
|
|
}()
|
|
var navigationItemsViews = [UIView]()
|
|
|
|
var landscapeTitleFont = UIFont.systemFontOfSize(14)
|
|
var portraitTitleFont = UIFont.systemFontOfSize(18)
|
|
|
|
required public init?(coder aDecoder: NSCoder) {
|
|
super.init(coder: aDecoder)
|
|
delegate = self
|
|
datasource = self
|
|
}
|
|
|
|
public override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
if navigationView.superview == nil {
|
|
navigationItem.titleView = navigationView
|
|
}
|
|
|
|
navigationView.addObserver(self, forKeyPath: "frame", options: [.New, .Old], context: nil)
|
|
navigationView.frame = CGRectMake(0, 0, CGRectGetWidth(navigationController!.navigationBar.frame), CGRectGetHeight(navigationController!.navigationBar.frame))
|
|
|
|
if navigationScrollView.superview == nil {
|
|
navigationView.addSubview(navigationScrollView)
|
|
}
|
|
if navigationPageControl.superview == nil {
|
|
navigationView.addSubview(navigationPageControl)
|
|
}
|
|
|
|
reloadNavigationViewItems()
|
|
}
|
|
|
|
public override func reloadPagerTabStripView() {
|
|
super.reloadPagerTabStripView()
|
|
guard isViewLoaded() else { return }
|
|
|
|
reloadNavigationViewItems()
|
|
setNavigationViewItemsPosition()
|
|
}
|
|
|
|
// 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: CGFloat, indexWasChanged: Bool) throws {
|
|
let distance = getDistanceValue()
|
|
var xOffset: CGFloat = 0
|
|
|
|
if fromIndex < toIndex {
|
|
xOffset = distance * CGFloat(fromIndex) + distance * progressPercentage
|
|
}
|
|
else if fromIndex > toIndex {
|
|
xOffset = distance * CGFloat(fromIndex) - distance * progressPercentage
|
|
}
|
|
else {
|
|
xOffset = distance * CGFloat(fromIndex)
|
|
}
|
|
|
|
navigationScrollView.contentOffset = CGPointMake(xOffset, 0)
|
|
setAlphaWithOffset(xOffset)
|
|
navigationPageControl.currentPage = currentIndex
|
|
}
|
|
|
|
public override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
|
|
guard object as! UIView == navigationView && keyPath! == "frame" && change![NSKeyValueChangeKindKey] as! UInt == NSKeyValueChange.Setting.rawValue else { return }
|
|
|
|
let oldRect = change![NSKeyValueChangeOldKey]!.CGRectValue
|
|
let newRect = change![NSKeyValueChangeOldKey]!.CGRectValue
|
|
guard !CGRectEqualToRect(oldRect, newRect) else { return }
|
|
|
|
navigationScrollView.frame = CGRectMake(0, 0, CGRectGetWidth(navigationView.frame), CGRectGetHeight(navigationScrollView.frame))
|
|
setNavigationViewItemsPosition()
|
|
}
|
|
|
|
deinit {
|
|
navigationView.removeObserver(self, forKeyPath: "frame")
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
func reloadNavigationViewItems() {
|
|
for item in navigationItemsViews {
|
|
item.removeFromSuperview()
|
|
}
|
|
|
|
navigationItemsViews.removeAll()
|
|
|
|
for (index, item) in viewControllers.enumerate() {
|
|
let child = item as! PagerTabStripChildItem
|
|
let childHeader = child.childHeaderForPagerTabStripViewController(self)
|
|
|
|
let navTitleLabel = createNewLabelWithText(childHeader.title)
|
|
navTitleLabel.alpha = currentIndex == index ? 1 : 0
|
|
navTitleLabel.textColor = childHeader.color ?? .whiteColor()
|
|
navigationScrollView.addSubview(navTitleLabel)
|
|
navigationItemsViews.append(navTitleLabel)
|
|
}
|
|
}
|
|
|
|
private func setNavigationViewItemsPosition() {
|
|
setNavigationViewItemsPosition(true)
|
|
}
|
|
|
|
private func setNavigationViewItemsPosition(updateAlpha: Bool) {
|
|
let distance = getDistanceValue()
|
|
let isPortrait = UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation)
|
|
let labelHeightSpace: CGFloat = isPortrait ? 34 : 25
|
|
for (index, view) in navigationItemsViews.enumerate() {
|
|
let label = view as! UILabel
|
|
if updateAlpha {
|
|
label.alpha = currentIndex == index ? 1 : 0
|
|
}
|
|
label.font = isPortrait ? portraitTitleFont : landscapeTitleFont
|
|
let viewSize = getLabelSize(label)
|
|
let originX = distance - viewSize.width/2 + CGFloat(index) * distance
|
|
let originY = (CGFloat(labelHeightSpace) - viewSize.height) / 2
|
|
label.frame = CGRectMake(originX, originY + 2, viewSize.width, viewSize.height)
|
|
label.tag = index
|
|
}
|
|
|
|
let xOffset = distance * CGFloat(currentIndex)
|
|
navigationScrollView.contentOffset = CGPointMake(xOffset, 0)
|
|
|
|
navigationPageControl.numberOfPages = navigationItemsViews.count
|
|
navigationPageControl.currentPage = currentIndex
|
|
let viewSize = navigationPageControl.sizeForNumberOfPages(navigationItemsViews.count)
|
|
let originX = distance - viewSize.width/2
|
|
navigationPageControl.frame = CGRectMake(originX, labelHeightSpace, viewSize.width, viewSize.height)
|
|
}
|
|
|
|
private func setAlphaWithOffset(xOffset: CGFloat) {
|
|
let distance = getDistanceValue()
|
|
for (index, view) in navigationItemsViews.enumerate() {
|
|
var alpha: CGFloat = 0
|
|
if xOffset < distance * CGFloat(index) {
|
|
alpha = (xOffset - distance * CGFloat(index - 1)) / distance
|
|
}
|
|
else {
|
|
alpha = 1 - ((xOffset - distance * CGFloat(index)) / distance)
|
|
}
|
|
view.alpha = alpha
|
|
}
|
|
}
|
|
|
|
private func createNewLabelWithText(text :String) -> UILabel {
|
|
let label = UILabel()
|
|
label.text = text
|
|
label.font = landscapeTitleFont
|
|
label.textColor = .whiteColor()
|
|
label.alpha = 0
|
|
return label
|
|
}
|
|
|
|
private func getLabelSize(label: UILabel) -> CGSize {
|
|
return (label.text! as NSString).sizeWithAttributes([NSFontAttributeName : label.font])
|
|
}
|
|
|
|
private func getDistanceValue() -> CGFloat {
|
|
let middle = navigationController?.navigationBar .convertPoint(navigationController!.navigationBar.center, toView: navigationView)
|
|
return middle!.x
|
|
}
|
|
|
|
public override func viewDidLayoutSubviews() {
|
|
super.viewDidLayoutSubviews()
|
|
setNavigationViewItemsPosition(false)
|
|
}
|
|
}
|