Repository: lucoceano/Pager
Branch: master
Commit: 390520b7503b
Files: 22
Total size: 74.5 KB
Directory structure:
gitextract_q9l42mii/
├── .gitignore
├── .swift-version
├── .swiftlint.yml
├── LICENSE
├── Pager/
│ ├── AppDelegate.swift
│ ├── Base.lproj/
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── Extensions.swift
│ ├── GreyDetailViewController.swift
│ ├── GreyViewController.swift
│ ├── Images.xcassets/
│ │ └── AppIcon.appiconset/
│ │ └── Contents.json
│ ├── Info.plist
│ ├── ViewController.swift
│ └── library/
│ ├── PagerController.swift
│ ├── TabView.swift
│ └── Utils.swift
├── Pager.podspec
├── Pager.xcodeproj/
│ ├── project.pbxproj
│ └── project.xcworkspace/
│ └── contents.xcworkspacedata
├── PagerTests/
│ ├── Info.plist
│ └── PagerTests.swift
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Swift template
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
================================================
FILE: .swift-version
================================================
3
================================================
FILE: .swiftlint.yml
================================================
disabled_rules:
- line_length
- type_name
- weak_delegate
force_cast: warning
function_body_length:
- 108
- 108
type_body_length:
- 720
- 720
file_length:
- 800
- 800
================================================
FILE: LICENSE
================================================
Copyright (c) 2014-2015 Meng To (meng@designcode.io)
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.
================================================
FILE: Pager/AppDelegate.swift
================================================
//
// AppDelegate.swift
// Pager
//
// Created by Lucas Oceano on 12/03/2015.
// Copyright (c) 2015 Cheesecake. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var navController: UINavigationController!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let viewController = ViewController()
let barButtomItem = UIBarButtonItem(title: "Purple Tab", style: .plain, target: viewController, action: #selector(ViewController.changeTab))
//NavigationController with title and button
navController = UINavigationController(rootViewController: viewController)
navController.navigationBar.topItem?.title = "Pager"
navController.navigationBar.topItem?.rightBarButtonItem = barButtomItem
navController.navigationBar.hideBottomHairline()
self.window!.rootViewController = navController
self.window?.makeKeyAndVisible()
//NavigationBar customization
UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().barTintColor = UIColor(rgb: 0x00AA00)
UINavigationBar.appearance().tintColor = UIColor.white
//Setting Status Bar to be white instead of black
UIApplication.shared.statusBarStyle = .lightContent
return true
}
}
================================================
FILE: Pager/Base.lproj/LaunchScreen.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Pager" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>
================================================
FILE: Pager/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="vXZ-lx-hvc">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="ufC-wZ-h7g">
<objects>
<viewController id="vXZ-lx-hvc" customClass="ViewController" customModule="Pager" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="jyV-Pf-zRb"/>
<viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="368" y="524"/>
</scene>
<!--View Controller-->
<scene sceneID="gQc-Ea-SiI">
<objects>
<viewController storyboardIdentifier="firstView" useStoryboardIdentifierAsRestorationIdentifier="YES" id="1zo-OV-UWc" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="OZ3-Ow-VRi"/>
<viewControllerLayoutGuide type="bottom" id="3C2-7v-M31"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="MgU-mq-XYz">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.1529411765" green="0.44705882349999998" blue="0.85882352939999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="5py-S7-fGe" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="331" y="-970"/>
</scene>
<!--View Controller-->
<scene sceneID="p3s-xC-Rds">
<objects>
<viewController storyboardIdentifier="secondView" useStoryboardIdentifierAsRestorationIdentifier="YES" id="n4d-Z2-8ks" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="aM8-JA-6zy"/>
<viewControllerLayoutGuide type="bottom" id="hzL-I0-bfJ"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="c1O-bK-eye">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="0.4823529412" blue="0.24313725489999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="NR5-mV-eKv" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="331" y="-286"/>
</scene>
<!--View Controller-->
<scene sceneID="55S-xs-UAp">
<objects>
<viewController storyboardIdentifier="thirdView" useStoryboardIdentifierAsRestorationIdentifier="YES" id="kyj-cI-Iw7" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="W2G-8Z-Ymx"/>
<viewControllerLayoutGuide type="bottom" id="YMZ-Yh-eK8"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="dr0-7C-kZQ">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.0" green="0.50196081400000003" blue="1" alpha="0.53767254600000003" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="ILt-5x-skm" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1001" y="-970"/>
</scene>
<!--Grey View Controller-->
<scene sceneID="Xs7-Vc-2S9">
<objects>
<viewController storyboardIdentifier="tableView" useStoryboardIdentifierAsRestorationIdentifier="YES" id="H57-mS-ztf" customClass="GreyViewController" customModule="Pager" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ifj-Js-KiO"/>
<viewControllerLayoutGuide type="bottom" id="hCi-BB-Gam"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="FmI-oN-uga">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="51H-bR-xZD">
<frame key="frameInset" minY="20" width="600" height="580"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="sectionIndexBackgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" id="eLg-Zg-8LV">
<rect key="frame" x="0.0" y="28" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="eLg-Zg-8LV" id="kEE-Hw-NZe">
<frame key="frameInset" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="H57-mS-ztf" id="THd-FS-qR6"/>
<outlet property="delegate" destination="H57-mS-ztf" id="lfF-3P-zah"/>
</connections>
</tableView>
</subviews>
<color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="hCi-BB-Gam" firstAttribute="top" secondItem="51H-bR-xZD" secondAttribute="bottom" id="1VE-IV-OaG"/>
<constraint firstItem="51H-bR-xZD" firstAttribute="leading" secondItem="FmI-oN-uga" secondAttribute="leading" id="7TA-tP-68e"/>
<constraint firstItem="51H-bR-xZD" firstAttribute="top" secondItem="Ifj-Js-KiO" secondAttribute="bottom" id="eo4-OK-mXb"/>
<constraint firstAttribute="trailing" secondItem="51H-bR-xZD" secondAttribute="trailing" id="kZf-Mh-ujg"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="VzX-0w-rBu"/>
<connections>
<outlet property="tableView" destination="51H-bR-xZD" id="Hab-Em-2s1"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="2wY-rf-DTh" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1647" y="-300"/>
</scene>
<!--View Controller-->
<scene sceneID="bbe-lW-Uf8">
<objects>
<viewController storyboardIdentifier="fifthView" useStoryboardIdentifierAsRestorationIdentifier="YES" id="nfu-RX-qo8" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="uqJ-Fg-tHs"/>
<viewControllerLayoutGuide type="bottom" id="IiA-jo-OE2"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="LWP-HA-K7H">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.36470588240000001" green="0.29411764709999999" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8ph-uc-38n" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1647" y="-970"/>
</scene>
<!--View Controller-->
<scene sceneID="Hs7-6G-3RK">
<objects>
<viewController storyboardIdentifier="sixthView" useStoryboardIdentifierAsRestorationIdentifier="YES" id="FMe-JW-F5b" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="gKv-d1-6Jd"/>
<viewControllerLayoutGuide type="bottom" id="o6d-27-HyS"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="9mv-Wn-QEk">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.1137254902" green="0.45098039220000002" blue="0.023529411760000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="IPG-Oa-trF" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2459" y="-286"/>
</scene>
<!--Grey Detail View Controller-->
<scene sceneID="GQz-KI-zC5">
<objects>
<viewController storyboardIdentifier="greyTableDetail" id="B85-7i-ZVT" customClass="GreyDetailViewController" customModule="Pager" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="bw5-4q-UcT"/>
<viewControllerLayoutGuide type="bottom" id="eL3-g9-SQx"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ptc-WH-4iP">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Detail for index 3" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5vr-gj-1f0">
<frame key="frameInset" minX="235.5" minY="289" width="129.5" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="5vr-gj-1f0" firstAttribute="centerY" secondItem="Ptc-WH-4iP" secondAttribute="centerY" id="BZX-xV-xcQ"/>
<constraint firstItem="5vr-gj-1f0" firstAttribute="centerX" secondItem="Ptc-WH-4iP" secondAttribute="centerX" id="Gv2-UY-otv"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="UAS-DR-xop"/>
<connections>
<outlet property="detailText" destination="5vr-gj-1f0" id="azd-wE-YGA"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="boJ-RP-lcC" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3721" y="-334"/>
</scene>
</scenes>
</document>
================================================
FILE: Pager/Extensions.swift
================================================
//
// Extensions.swift
// Pager
//
// Created by Lucas Farah on 3/20/16.
// Copyright © 2016 Cheesecake. All rights reserved.
//
import UIKit
extension UIColor {
convenience init(rgb: UInt) {
self.init(
red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgb & 0x0000FF) / 255.0,
alpha: CGFloat(1.0)
)
}
}
extension UINavigationBar {
func hideBottomHairline() {
let navigationBarImageView = hairlineImageViewInNavigationBar(self)
navigationBarImageView!.isHidden = true
}
func showBottomHairline() {
let navigationBarImageView = hairlineImageViewInNavigationBar(self)
navigationBarImageView!.isHidden = false
}
fileprivate func hairlineImageViewInNavigationBar(_ view: UIView) -> UIImageView? {
if let view = view as? UIImageView, view.bounds.size.height <= 1.0 {
return view
}
let subviews = (view.subviews as [UIView])
for subview: UIView in subviews {
if let imageView: UIImageView = hairlineImageViewInNavigationBar(subview) {
return imageView
}
}
return nil
}
}
================================================
FILE: Pager/GreyDetailViewController.swift
================================================
//
// GreyDetailViewController.swift
// Pager
//
// Created by Antonio Alves on 8/16/16.
// Copyright © 2016 Cheesecake. All rights reserved.
//
import UIKit
class GreyDetailViewController: UIViewController {
@IBOutlet weak var detailText: UILabel! {
didSet {
detailText.text = text
}
}
var text: String?
}
================================================
FILE: Pager/GreyViewController.swift
================================================
//
// GreyViewController.swift
// Pager
//
// Created by Antonio Alves on 8/16/16.
// Copyright © 2016 Cheesecake. All rights reserved.
//
import UIKit
class GreyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var didSelectRow: ((String) -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
automaticallyAdjustsScrollViewInsets = false
}
// MARK: - Table view data source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 10
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath)
cell.textLabel?.text = "Example at index \(indexPath.row + 1)"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
didSelectRow?("Detail for index \(indexPath.row + 1)")
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
}
================================================
FILE: Pager/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Pager/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Pager</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
================================================
FILE: Pager/ViewController.swift
================================================
//
// ViewController.swift
// Pager
//
// Created by Lucas Oceano on 12/03/2015.
// Copyright (c) 2015 Cheesecake. All rights reserved.
//
import UIKit
class ViewController: PagerController, PagerDataSource {
var titles: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
// Instantiating Storyboard ViewControllers
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller1 = storyboard.instantiateViewController(withIdentifier: "firstView")
let controller2 = storyboard.instantiateViewController(withIdentifier: "secondView")
let controller3 = storyboard.instantiateViewController(withIdentifier: "thirdView")
let controller4 = storyboard.instantiateViewController(withIdentifier: "tableView")
let controller5 = storyboard.instantiateViewController(withIdentifier: "fifthView")
let controller6 = storyboard.instantiateViewController(withIdentifier: "sixthView")
// Setting up the PagerController with Name of the Tabs and their respective ViewControllers
self.setupPager(
tabNames: ["Blue", "Orange", "Light Blue", "Grey", "Purple", "Green"],
tabControllers: [controller1, controller2, controller3, controller4, controller5, controller6])
customizeTab()
if let controller = controller4 as? GreyViewController {
controller.didSelectRow = { [weak self] (text: String) in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let detail = storyboard.instantiateViewController(withIdentifier: "greyTableDetail") as? GreyDetailViewController {
detail.text = text
self?.navigationController?.pushViewController(detail, animated: true)
}
}
}
}
// Customising the Tab's View
func customizeTab() {
indicatorColor = UIColor.white
tabsViewBackgroundColor = UIColor(rgb: 0x00AA00)
contentViewBackgroundColor = UIColor.gray.withAlphaComponent(0.32)
startFromSecondTab = false
centerCurrentTab = true
tabLocation = PagerTabLocation.top
tabHeight = 49
tabOffset = 36
tabWidth = 96.0
fixFormerTabsPositions = false
fixLaterTabsPosition = false
animation = PagerAnimation.during
selectedTabTextColor = .blue
tabsTextFont = UIFont(name: "HelveticaNeue-Bold", size: 20)!
// tabTopOffset = 10.0
// tabsTextColor = .purpleColor()
}
// Programatically selecting a tab. This function is getting called on AppDelegate
@objc func changeTab() {
self.selectTabAtIndex(4)
}
}
================================================
FILE: Pager/library/PagerController.swift
================================================
//
// ViewPager.swift
// Pager
//
// Created by Lucas Oceano on 12/03/2015.
// Copyright (c) 2015 Cheesecake. All rights reserved.
//
import Foundation
import UIKit.UITableView
// MARK: - Pager Enums
//Enum for the location of the tab bar
public enum PagerTabLocation: Int {
case none = 0 // None will go to the bottom
case top = 1
case bottom = 2
}
//Enum for the animation of the tab indicator
public enum PagerAnimation: Int {
case none = 0 // No animation
case end = 1 // pager indicator will animate after the VC changes
case during = 2 // pager indicator will animate as the VC changes
}
// MARK: - Protocols
@objc public protocol PagerDelegate: NSObjectProtocol {
@objc optional func didChangeTabToIndex(_ pager: PagerController, index: Int)
@objc optional func didChangeTabToIndex(_ pager: PagerController, index: Int, previousIndex: Int)
@objc optional func didChangeTabToIndex(_ pager: PagerController, index: Int, previousIndex: Int, swipe: Bool)
}
@objc public protocol PagerDataSource: NSObjectProtocol {
@objc optional func numberOfTabs(_ pager: PagerController) -> Int
@objc optional func tabViewForIndex(_ index: Int, pager: PagerController) -> UIView
@objc optional func viewForTabAtIndex(_ index: Int, pager: PagerController) -> UIView
@objc optional func controllerForTabAtIndex(_ index: Int, pager: PagerController) -> UIViewController
}
open class PagerController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate, UIScrollViewDelegate {
// MARK: - public properties
open var contentViewBackgroundColor: UIColor = UIColor.white
open var indicatorColor: UIColor = UIColor.red
open var tabsViewBackgroundColor: UIColor = UIColor.gray
open var tabsTextColor: UIColor = UIColor.white
open var selectedTabTextColor = UIColor.white
open var tabsImageViewContentMode = UIViewContentMode.scaleAspectFit
open weak var dataSource: PagerDataSource?
open weak var delegate: PagerDelegate?
open var tabHeight: CGFloat = 44.0
open var tabTopOffset: CGFloat = 0.0
open var tabOffset: CGFloat = 56.0
open var tabWidth: CGFloat = 128.0
open var tabsTextFont: UIFont = UIFont.boldSystemFont(ofSize: 16.0)
open var indicatorHeight: CGFloat = 5.0
open var tabLocation: PagerTabLocation = PagerTabLocation.top
open var animation: PagerAnimation = PagerAnimation.during
open var startFromSecondTab: Bool = false
open var centerCurrentTab: Bool = false
open var fixFormerTabsPositions: Bool = false
open var fixLaterTabsPosition: Bool = false
open var ignoreTopBarHeight: Bool = false
open var ignoreBottomBarHeight: Bool = false
fileprivate var tabViews: [UIView] = []
fileprivate var tabControllers: [UIViewController] = []
// MARK: - Tab and content stuff
internal var tabsView: UIScrollView?
internal var pageViewController: UIPageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
internal var actualDelegate: UIScrollViewDelegate?
internal var contentView: UIView {
let contentView = self.pageViewController.view
contentView!.autoresizingMask = [.flexibleHeight, .flexibleWidth]
contentView!.backgroundColor = self.contentViewBackgroundColor
contentView!.bounds = self.view.bounds
contentView!.tag = 34
return contentView!
}
// MARK: - Tab and content cache
internal var underlineStroke: UIView = UIView()
internal var tabs: [UIView?] = []
internal var contents: [UIViewController?] = []
internal var tabCount: Int = 0
internal var activeTabIndex: Int = 0
internal var activeContentIndex: Int = 0
internal var animatingToTab: Bool = false
internal var defaultSetupDone: Bool = false
internal var didTapOnTabView: Bool = false
// MARK: - Important Methods
// Initializing PagerController with Name of the Tabs and their respective ViewControllers
open func setupPager(tabNames: [String], tabControllers: [UIViewController]) {
let tabViews = tabNames.map { title -> UILabel in
let label = UILabel()
label.text = title
label.textColor = tabsTextColor
label.font = tabsTextFont
label.backgroundColor = .clear
label.sizeToFit()
return label
}
setupPager(views: tabViews, tabControllers: tabControllers)
}
open func setupPager(tabImages: [UIImage], tabControllers: [UIViewController]) {
let tabViews = tabImages.map { image -> UIImageView in
let imageView = UIImageView(image: image)
imageView.contentMode = tabsImageViewContentMode
imageView.backgroundColor = .clear
return imageView
}
setupPager(views: tabViews, tabControllers: tabControllers)
}
open func setupPager(views: [UIView], tabControllers: [UIViewController]) {
self.tabViews = views
self.tabControllers = tabControllers
}
open func reloadData() {
self.defaultSetup()
self.view.setNeedsDisplay()
}
open func selectTabAtIndex(_ index: Int) {
self.selectTabAtIndex(index, swipe: false)
}
// MARK: - Other Methods
override open func viewDidLoad() {
super.viewDidLoad()
self.defaultSettings()
}
override open func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if !self.defaultSetupDone {
self.defaultSetup()
}
}
override open func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.layoutSubViews()
}
open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
self.layoutSubViews()
self.changeActiveTabIndex(self.activeTabIndex)
}
override open func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Private Methods
func defaultSettings() {
for (view): (UIView) in self.pageViewController.view!.subviews as [UIView] {
if let view = view as? UIScrollView {
self.actualDelegate = view.delegate
view.delegate = self
}
}
self.pageViewController.dataSource = self
self.pageViewController.delegate = self
}
func defaultSetup() {
// Empty tabs and contents
self.tabs.forEach { (tabView) in
tabView?.removeFromSuperview()
}
self.tabs.removeAll(keepingCapacity: true)
self.contents.removeAll(keepingCapacity: true)
self.underlineStroke.removeFromSuperview()
// Get tabCount from dataSource
if let dataSource = self.dataSource,
let num = dataSource.numberOfTabs?(self) {
self.tabCount = num
} else {
self.tabCount = tabControllers.count
}
// Populate arrays with nil
self.tabs = Array(repeating: nil, count: self.tabCount)
for _ in 0 ..< self.tabCount {
self.tabs.append(nil)
}
self.contents = Array(repeating: nil, count: self.tabCount)
for _ in 0 ..< self.tabCount {
self.contents.append(nil)
}
// Add tabsView
if self.tabsView == nil {
self.tabsView = UIScrollView(frame: CGRect(x: 0.0, y: 0.0, width: self.view.frame.width, height: self.tabHeight))
self.tabsView!.autoresizingMask = .flexibleWidth
self.tabsView!.backgroundColor = self.tabsViewBackgroundColor
self.tabsView!.scrollsToTop = false
self.tabsView?.bounces = false
self.tabsView!.showsHorizontalScrollIndicator = false
self.tabsView!.showsVerticalScrollIndicator = false
self.tabsView?.isScrollEnabled = true
self.tabsView!.tag = 38
self.view.insertSubview(self.tabsView!, at: 0)
} else {
self.tabsView = self.view.viewWithTag(38) as? UIScrollView
}
// Add tab views to _tabsView
var contentSizeWidth: CGFloat = 0.0
// Give the standard offset if fixFormerTabsPositions is provided as YES
if self.fixFormerTabsPositions {
// And if the centerCurrentTab is provided as YES fine tune the offset according to it
if self.centerCurrentTab {
contentSizeWidth = (self.tabsView!.frame.width - self.tabWidth) / 2.0
} else {
contentSizeWidth = self.tabOffset
}
}
for i in 0 ..< self.tabCount {
let tabView: UIView? = self.tabViewAtIndex(i) as UIView?
var frame: CGRect = tabView!.frame
frame.origin.x = contentSizeWidth
frame.size.width = self.tabWidth
tabView!.frame = frame
self.tabsView!.addSubview(tabView!)
contentSizeWidth += tabView!.frame.width
// To capture tap events
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(PagerController.handleTapGesture(_:)))
tabView!.addGestureRecognizer(tapGestureRecognizer)
}
// Extend contentSizeWidth if fixLatterTabsPositions is provided YES
if self.fixLaterTabsPosition {
// And if the centerCurrentTab is provided as YES fine tune the content size according to it
if self.centerCurrentTab {
contentSizeWidth += (self.tabsView!.frame.width - self.tabWidth) / 2.0
} else {
contentSizeWidth += self.tabsView!.frame.width - self.tabWidth - self.tabOffset
}
}
self.tabsView!.contentSize = CGSize(width: contentSizeWidth, height: self.tabHeight)
self.view.insertSubview(self.contentView, at: 0)
// Select starting tab
let index: Int = self.startFromSecondTab ? 1 : 0
self.selectTabAtIndex(index, swipe: true)
if self.tabCount > 0 {
// creates the indicator
var rect: CGRect = self.tabViewAtIndex(self.activeContentIndex)!.frame
rect.origin.y = rect.size.height - self.indicatorHeight
rect.size.height = self.indicatorHeight
self.underlineStroke = UIView(frame: rect)
self.underlineStroke.backgroundColor = self.indicatorColor
self.tabsView!.addSubview(self.underlineStroke)
}
// Set setup done
self.defaultSetupDone = true
}
func layoutSubViews() {
var topLayoutGuide: CGFloat = 0.0
if !ignoreTopBarHeight && self.navigationController?.navigationBar.isTranslucent != false {
topLayoutGuide = UIApplication.shared.isStatusBarHidden ? 0.0 : 20.0
if UIDevice.isIphoneX {
topLayoutGuide += 24.0
}
if let nav = self.navigationController {
topLayoutGuide += nav.navigationBar.frame.size.height
}
}
var frame: CGRect = self.tabsView!.frame
frame.origin.x = 0.0
frame.origin.y = (self.tabLocation == .top) ? topLayoutGuide + tabTopOffset: self.view.frame.height - self.tabHeight
frame.size.width = self.view.frame.width
frame.size.height = self.tabHeight
self.tabsView!.frame = frame
frame = self.contentView.frame
frame.origin.x = 0.0
frame.origin.y = (self.tabLocation == .top) ? topLayoutGuide + self.tabsView!.frame.height + tabTopOffset: topLayoutGuide
frame.size.width = self.view.frame.width
frame.size.height = self.view.frame.height - (topLayoutGuide + self.tabsView!.frame.height + tabTopOffset)
if !ignoreBottomBarHeight && self.tabBarController != nil && self.tabBarController?.tabBar.isTranslucent == true {
frame.size.height -= self.tabBarController!.tabBar.frame.height
}
self.contentView.frame = frame
}
func indexForViewController(_ viewController: UIViewController) -> Int {
for (index, element) in self.contents.enumerated() where element == viewController {
return index
}
return 0
}
func selectTabAtIndex(_ index: Int, swipe: Bool) {
if index >= self.tabCount {
return
}
self.didTapOnTabView = !swipe
self.animatingToTab = true
let previousIndex: Int = self.activeTabIndex
self.changeActiveTabIndex(index)
self.setActiveContentIndex(index)
if self.delegate != nil {
if self.delegate!.responds(to: #selector(PagerDelegate.didChangeTabToIndex(_: index:))) {
self.delegate!.didChangeTabToIndex!(self, index: index)
} else if self.delegate!.responds(to: #selector(PagerDelegate.didChangeTabToIndex(_: index: previousIndex:))) {
self.delegate!.didChangeTabToIndex!(self, index: index, previousIndex: previousIndex)
} else if self.delegate!.responds(to: #selector(PagerDelegate.didChangeTabToIndex(_: index: previousIndex: swipe:))) {
self.delegate!.didChangeTabToIndex!(self, index: index, previousIndex: previousIndex, swipe: swipe)
}
}
// Updating selected tab color
updateSelectedTab(index)
}
func updateSelectedTab(_ index: Int) {
// Resetting all tab colors to white
for tab in self.tabs {
if let label = tab?.subviews.first as? UILabel {
label.textColor = tabsTextColor
}
}
// Setting current selected tab to red
let tab = self.tabViewAtIndex(index)
if let label = tab?.subviews.first as? UILabel {
label.textColor = selectedTabTextColor
}
}
func changeActiveTabIndex(_ newIndex: Int) {
self.activeTabIndex = newIndex
let tabView: UIView = self.tabViewAtIndex(self.activeTabIndex)!
var frame: CGRect = tabView.frame
if self.centerCurrentTab {
if (frame.origin.x + frame.width + (self.tabsView!.frame.width / 2)) >= self.tabsView!.contentSize.width {
frame.origin.x = (self.tabsView!.contentSize.width - self.tabsView!.frame.width)
} else {
frame.origin.x += (frame.width / 2)
frame.origin.x -= (self.tabsView!.frame.width / 2)
if frame.origin.x < 0 {
frame.origin.x = 0
}
}
} else {
frame.origin.x -= self.tabOffset
frame.size.width = self.tabsView!.frame.width
}
self.tabsView!.setContentOffset(frame.origin, animated: true)
}
func tabViewAtIndex(_ index: Int) -> TabView? {
guard
let dataSource = self.dataSource,
index < self.tabCount
else {
return nil
}
if (self.tabs[index] as UIView?) == nil {
var tabViewContent = UIView()
if let tab = dataSource.tabViewForIndex?(index, pager: self) {
tabViewContent = tab
} else {
tabViewContent = tabViews[index]
}
tabViewContent.autoresizingMask = [.flexibleHeight, .flexibleWidth]
let tabView: TabView = TabView(frame: CGRect(x: 0.0, y: 0.0, width: self.tabWidth, height: self.tabHeight))
tabView.addSubview(tabViewContent)
tabView.clipsToBounds = true
tabViewContent.center = tabView.center
// Replace the null object with tabView
self.tabs[index] = tabView
}
return self.tabs[index] as? TabView
}
func setNeedsReloadOptions() {
// We should update contentSize property of our tabsView, so we should recalculate it with the new values
var contentSizeWidth: CGFloat = 0.0
// Give the standard offset if fixFormerTabsPositions is provided as YES
if self.fixFormerTabsPositions {
// And if the centerCurrentTab is provided as YES fine tune the offset according to it
if self.centerCurrentTab {
contentSizeWidth = (self.tabsView!.frame.width - self.tabWidth) / 2.0
} else {
contentSizeWidth = self.tabOffset
}
}
// Update every tab's frame
for i in 0 ..< self.tabCount {
let tabView = self.tabViewAtIndex(i)
var frame: CGRect = tabView!.frame
frame.origin.x = contentSizeWidth
frame.size.width = self.tabWidth
tabView?.frame = frame
contentSizeWidth += tabView!.frame.width
}
// Extend contentSizeWidth if fixLatterTabsPositions is provided YES
if self.fixLaterTabsPosition {
// And if the centerCurrentTab is provided as YES fine tune the content size according to it
if self.centerCurrentTab {
contentSizeWidth += (self.tabsView!.frame.width - self.tabWidth) / 2.0
} else {
contentSizeWidth += self.tabsView!.frame.width - self.tabWidth - self.tabOffset
}
}
// Update tabsView's contentSize with the new width
self.tabsView!.contentSize = CGSize(width: contentSizeWidth, height: self.tabHeight)
}
func viewControllerAtIndex(_ index: Int) -> UIViewController? {
guard
let dataSource = self.dataSource,
index < self.tabCount && index >= 0
else {
return nil
}
if (self.contents[index] as UIViewController?) == nil {
var viewController: UIViewController
if dataSource.responds(to: #selector(PagerDataSource.controllerForTabAtIndex(_: pager:))) {
viewController = dataSource.controllerForTabAtIndex!(index, pager: self)
} else if dataSource.responds(to: #selector(PagerDataSource.viewForTabAtIndex(_: pager:))) {
let view: UIView = dataSource.viewForTabAtIndex!(index, pager: self)
// Adjust view's bounds to match the pageView's bounds
let pageView: UIView = self.view.viewWithTag(34)!
view.frame = pageView.bounds
viewController = UIViewController()
viewController.view = view
} else {
viewController = self.tabControllers[index]
}
self.contents[index] = viewController
self.pageViewController.addChildViewController(viewController)
}
return self.contents[index]
}
// MARK: - Gestures
@IBAction func handleTapGesture(_ sender: UITapGestureRecognizer) {
let tabView: UIView = sender.view!
let index: Int = self.tabs.find {
$0 as UIView? == tabView
}!
if self.activeTabIndex != index {
self.selectTabAtIndex(index)
}
}
// MARK: - Page DataSource
open func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
var index: Int = self.indexForViewController(viewController)
index -= 1
return self.viewControllerAtIndex(index)
}
open func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
var index: Int = self.indexForViewController(viewController)
index += 1
return self.viewControllerAtIndex(index)
}
// MARK: - Page Delegate
open func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
let viewController: UIViewController = self.pageViewController.viewControllers![0] as UIViewController
let index: Int = self.indexForViewController(viewController)
self.selectTabAtIndex(index, swipe: true)
}
@nonobjc func setActiveContentIndex(_ activeContentIndex: Int) {
// Get the desired viewController
var viewController: UIViewController? = self.viewControllerAtIndex(activeContentIndex)!
if viewController == nil {
viewController = UIViewController()
viewController!.view = UIView()
viewController!.view.backgroundColor = UIColor.clear
}
weak var wPageViewController: UIPageViewController? = self.pageViewController
weak var wSelf: PagerController? = self
if activeContentIndex == self.activeContentIndex {
DispatchQueue.main.async(execute: {
self.pageViewController.setViewControllers([viewController!], direction: .forward, animated: false, completion: { _ -> Void in
wSelf!.animatingToTab = false
})
})
} else if !(activeContentIndex + 1 == self.activeContentIndex || activeContentIndex - 1 == self.activeContentIndex) {
let direction: UIPageViewControllerNavigationDirection = (activeContentIndex < self.activeContentIndex) ? .reverse : .forward
DispatchQueue.main.async(execute: {
self.pageViewController.setViewControllers([viewController!], direction: direction, animated: true, completion: { completed in
wSelf?.animatingToTab = false
if completed {
DispatchQueue.main.async(execute: {
() -> Void in
wPageViewController!.setViewControllers([viewController!], direction: direction, animated: false, completion: nil)
})
}
})
})
} else {
let direction: UIPageViewControllerNavigationDirection = (activeContentIndex < self.activeContentIndex) ? .reverse : .forward
DispatchQueue.main.async(execute: {
self.pageViewController.setViewControllers([viewController!], direction: direction, animated: true, completion: { _ -> Void in
wSelf!.animatingToTab = true
})
})
}
// Clean out of sight contents
var index: Int = self.activeContentIndex - 1
if index >= 0 && index != activeContentIndex && index != activeContentIndex - 1 {
self.contents[index] = nil
}
index = self.activeContentIndex
if index != activeContentIndex - 1 && index != activeContentIndex && index != activeContentIndex + 1 {
self.contents[index] = nil
}
index = self.activeContentIndex + 1
if index < self.contents.count && index != activeContentIndex && index != activeContentIndex + 1 {
self.contents[index] = nil
}
self.activeContentIndex = activeContentIndex
}
// MARK: - UIScrollViewDelegate
// MARK: Responding to Scrolling and Dragging
open func scrollViewDidScroll(_ scrollView: UIScrollView) {
if self.actualDelegate?.responds(to: #selector(UIScrollViewDelegate.scrollViewDidScroll(_:))) ?? false {
self.actualDelegate?.scrollViewDidScroll?(scrollView)
}
let tabView: UIView = self.tabViewAtIndex(self.activeTabIndex)!
if !self.animatingToTab {
// Get the related tab view position
var frame: CGRect = tabView.frame
let movedRatio: CGFloat = (scrollView.contentOffset.x / scrollView.frame.width) - 1
frame.origin.x += movedRatio * frame.width
if self.centerCurrentTab {
frame.origin.x += (frame.size.width / 2)
frame.origin.x -= self.tabsView!.frame.width / 2
frame.size.width = self.tabsView!.frame.width
if frame.origin.x < 0 {
frame.origin.x = 0
}
if (frame.origin.x + frame.size.width) > self.tabsView!.contentSize.width {
frame.origin.x = (self.tabsView!.contentSize.width - self.tabsView!.frame.width)
}
} else {
frame.origin.x -= self.tabOffset
frame.size.width = self.tabsView!.frame.width
}
self.tabsView!.scrollRectToVisible(frame, animated: false)
}
var rect: CGRect = tabView.frame
let updateIndicator = {
(newX: CGFloat) -> Void in
rect.origin.x = newX
rect.origin.y = self.underlineStroke.frame.origin.y
rect.size.height = self.underlineStroke.frame.size.height
self.underlineStroke.frame = rect
}
var newX: CGFloat
let width: CGFloat = self.view.frame.width
let distance: CGFloat = tabView.frame.size.width
if self.animation == PagerAnimation.during && !self.didTapOnTabView {
if scrollView.panGestureRecognizer.translation(in: scrollView.superview!).x > 0 {
let mov: CGFloat = width - scrollView.contentOffset.x
newX = rect.origin.x - ((distance * mov) / width)
} else {
let mov: CGFloat = scrollView.contentOffset.x - width
newX = rect.origin.x + ((distance * mov) / width)
}
updateIndicator(newX)
} else if self.animation == PagerAnimation.none {
newX = tabView.frame.origin.x
updateIndicator(newX)
} else if self.animation == PagerAnimation.end || self.didTapOnTabView {
newX = tabView.frame.origin.x
UIView.animate(withDuration: 0.35, animations: {
() -> Void in
updateIndicator(newX)
})
}
}
open func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
if self.actualDelegate != nil {
if self.actualDelegate!.responds(to: #selector(UIScrollViewDelegate.scrollViewWillBeginDragging(_:))) {
self.actualDelegate!.scrollViewWillBeginDragging!(scrollView)
}
}
}
open func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if self.actualDelegate != nil {
if self.actualDelegate!.responds(to: #selector(UIScrollViewDelegate.scrollViewWillEndDragging(_: withVelocity: targetContentOffset:))) {
self.actualDelegate!.scrollViewWillEndDragging!(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset)
}
}
}
open func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if self.actualDelegate != nil {
if self.actualDelegate!.responds(to: #selector(UIScrollViewDelegate.scrollViewDidEndDragging(_: willDecelerate:))) {
self.actualDelegate!.scrollViewDidEndDragging!(scrollView, willDecelerate: decelerate)
}
}
self.didTapOnTabView = false
}
open func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
if self.actualDelegate != nil {
if self.actualDelegate!.responds(to: #selector(UIScrollViewDelegate.scrollViewShouldScrollToTop(_:))) {
return self.actualDelegate!.scrollViewShouldScrollToTop!(scrollView)
}
}
return false
}
open func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {
if self.actualDelegate != nil {
if self.actualDelegate!.responds(to: #selector(UIScrollViewDelegate.scrollViewDidScrollToTop(_:))) {
self.actualDelegate!.scrollViewDidScrollToTop!(scrollView)
}
}
}
open func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
if self.actualDelegate != nil {
if self.actualDelegate!.responds(to: #selector(UIScrollViewDelegate.scrollViewWillBeginDecelerating(_:))) {
self.actualDelegate!.scrollViewWillBeginDecelerating!(scrollView)
}
}
}
open func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if self.actualDelegate != nil {
if self.actualDelegate!.responds(to: #selector(UIScrollViewDelegate.scrollViewDidEndDecelerating(_:))) {
self.actualDelegate!.scrollViewDidEndDecelerating!(scrollView)
}
}
self.didTapOnTabView = false
}
// MARK: Managing Zooming
open func viewForZooming(in scrollView: UIScrollView) -> UIView? {
if self.actualDelegate?.responds(to: #selector(UIScrollViewDelegate.viewForZooming(in:))) ?? false {
return self.actualDelegate?.viewForZooming!(in: scrollView)
}
return nil
}
open func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
if self.actualDelegate?.responds(to: #selector(UIScrollViewDelegate.scrollViewWillBeginZooming(_:with:))) ?? false {
self.actualDelegate?.scrollViewWillBeginZooming!(scrollView, with: view)
}
}
open func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
if self.actualDelegate?.responds(to: #selector(UIScrollViewDelegate.scrollViewDidEndZooming(_:with:atScale:))) ?? false {
self.actualDelegate?.scrollViewDidEndZooming!(scrollView, with: view, atScale: scale)
}
}
open func scrollViewDidZoom(_ scrollView: UIScrollView) {
if self.actualDelegate?.responds(to: #selector(UIScrollViewDelegate.scrollViewDidZoom(_:))) ?? false {
self.actualDelegate?.scrollViewDidZoom!(scrollView)
}
}
// UIScrollViewDelegate, Responding to Scrolling Animations
open func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
if self.actualDelegate?.responds(to: #selector(UIScrollViewDelegate.scrollViewDidEndScrollingAnimation(_:))) ?? false {
self.actualDelegate?.scrollViewDidEndScrollingAnimation!(scrollView)
}
self.didTapOnTabView = false
}
}
================================================
FILE: Pager/library/TabView.swift
================================================
import UIKit
class TabView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clear
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.backgroundColor = UIColor.clear
}
}
================================================
FILE: Pager/library/Utils.swift
================================================
import UIKit
extension Array {
func find(_ includedElement: (Element) -> Bool) -> Int? {
for (idx, element) in self.enumerated() {
if includedElement(element) {
return idx
}
}
return 0
}
}
extension UIDevice {
static var isIphoneX: Bool {
var modelIdentifier = ""
if isSimulator {
modelIdentifier = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] ?? ""
} else {
var size = 0
sysctlbyname("hw.machine", nil, &size, nil, 0)
var machine = [CChar](repeating: 0, count: size)
sysctlbyname("hw.machine", &machine, &size, nil, 0)
modelIdentifier = String(cString: machine)
}
return modelIdentifier == "iPhone10,3" || modelIdentifier == "iPhone10,6"
}
static var isSimulator: Bool = TARGET_OS_SIMULATOR != 0
}
================================================
FILE: Pager.podspec
================================================
Pod::Spec.new do |s|
s.name = 'Pager'
s.version = '1.4.0'
s.license = 'MIT'
s.summary = 'Easily create sliding tabs with Pager.'
s.homepage = 'https://github.com/lucoceano/Pager'
s.authors = { 'Lucas Oceano' => 'lucoceano@ckl.io' }
s.source = { :git => 'https://github.com/lucoceano/Pager.git', :tag => s.version.to_s }
s.requires_arc = true
s.ios.deployment_target = '8.0'
s.source_files = 'Pager/library/*.swift'
end
================================================
FILE: Pager.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
C2652A591C9E894D00FE8F50 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2652A581C9E894D00FE8F50 /* Extensions.swift */; };
C876EF5F2042364400701C03 /* PagerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C876EF5E2042364300701C03 /* PagerController.swift */; };
C876EF612042366800701C03 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = C876EF602042366800701C03 /* Utils.swift */; };
C876EF63204236A500701C03 /* TabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C876EF62204236A500701C03 /* TabView.swift */; };
C8B7D13E1AB25F9300E9347C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B7D13D1AB25F9300E9347C /* AppDelegate.swift */; };
C8B7D1401AB25F9300E9347C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B7D13F1AB25F9300E9347C /* ViewController.swift */; };
C8B7D1431AB25F9300E9347C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C8B7D1411AB25F9300E9347C /* Main.storyboard */; };
C8B7D1451AB25F9300E9347C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C8B7D1441AB25F9300E9347C /* Images.xcassets */; };
C8B7D1481AB25F9300E9347C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = C8B7D1461AB25F9300E9347C /* LaunchScreen.xib */; };
C8E736D71D92CAD5001491E6 /* GreyDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8E736D51D92CAD5001491E6 /* GreyDetailViewController.swift */; };
C8E736D81D92CAD5001491E6 /* GreyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8E736D61D92CAD5001491E6 /* GreyViewController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
C2652A581C9E894D00FE8F50 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
C876EF5E2042364300701C03 /* PagerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagerController.swift; sourceTree = "<group>"; };
C876EF602042366800701C03 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
C876EF62204236A500701C03 /* TabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabView.swift; sourceTree = "<group>"; };
C8B7D1381AB25F9300E9347C /* Pager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Pager.app; sourceTree = BUILT_PRODUCTS_DIR; };
C8B7D13C1AB25F9300E9347C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C8B7D13D1AB25F9300E9347C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C8B7D13F1AB25F9300E9347C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
C8B7D1421AB25F9300E9347C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
C8B7D1441AB25F9300E9347C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
C8B7D1471AB25F9300E9347C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
C8B7D1521AB25F9300E9347C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C8B7D1531AB25F9300E9347C /* PagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PagerTests.swift; sourceTree = "<group>"; };
C8E736D51D92CAD5001491E6 /* GreyDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GreyDetailViewController.swift; sourceTree = "<group>"; };
C8E736D61D92CAD5001491E6 /* GreyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GreyViewController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
C8B7D1351AB25F9300E9347C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
C876EF5D2042364300701C03 /* library */ = {
isa = PBXGroup;
children = (
C876EF5E2042364300701C03 /* PagerController.swift */,
C876EF602042366800701C03 /* Utils.swift */,
C876EF62204236A500701C03 /* TabView.swift */,
);
path = library;
sourceTree = "<group>";
};
C8B7D12F1AB25F9300E9347C = {
isa = PBXGroup;
children = (
C8B7D13A1AB25F9300E9347C /* Pager */,
C8B7D1501AB25F9300E9347C /* PagerTests */,
C8B7D1391AB25F9300E9347C /* Products */,
);
sourceTree = "<group>";
};
C8B7D1391AB25F9300E9347C /* Products */ = {
isa = PBXGroup;
children = (
C8B7D1381AB25F9300E9347C /* Pager.app */,
);
name = Products;
sourceTree = "<group>";
};
C8B7D13A1AB25F9300E9347C /* Pager */ = {
isa = PBXGroup;
children = (
C8E736D51D92CAD5001491E6 /* GreyDetailViewController.swift */,
C8E736D61D92CAD5001491E6 /* GreyViewController.swift */,
C876EF5D2042364300701C03 /* library */,
C8B7D13D1AB25F9300E9347C /* AppDelegate.swift */,
C8B7D13F1AB25F9300E9347C /* ViewController.swift */,
C2652A581C9E894D00FE8F50 /* Extensions.swift */,
C8B7D1411AB25F9300E9347C /* Main.storyboard */,
C8B7D1441AB25F9300E9347C /* Images.xcassets */,
C8B7D1461AB25F9300E9347C /* LaunchScreen.xib */,
C8B7D13B1AB25F9300E9347C /* Supporting Files */,
);
path = Pager;
sourceTree = "<group>";
};
C8B7D13B1AB25F9300E9347C /* Supporting Files */ = {
isa = PBXGroup;
children = (
C8B7D13C1AB25F9300E9347C /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
C8B7D1501AB25F9300E9347C /* PagerTests */ = {
isa = PBXGroup;
children = (
C8B7D1531AB25F9300E9347C /* PagerTests.swift */,
C8B7D1511AB25F9300E9347C /* Supporting Files */,
);
path = PagerTests;
sourceTree = "<group>";
};
C8B7D1511AB25F9300E9347C /* Supporting Files */ = {
isa = PBXGroup;
children = (
C8B7D1521AB25F9300E9347C /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
C8B7D1371AB25F9300E9347C /* Pager */ = {
isa = PBXNativeTarget;
buildConfigurationList = C8B7D1571AB25F9300E9347C /* Build configuration list for PBXNativeTarget "Pager" */;
buildPhases = (
C8B7D1341AB25F9300E9347C /* Sources */,
C8B7D1351AB25F9300E9347C /* Frameworks */,
C8B7D1361AB25F9300E9347C /* Resources */,
C82DD78F1D95C0F200CF596E /* Swift lint */,
);
buildRules = (
);
dependencies = (
);
name = Pager;
productName = Pager;
productReference = C8B7D1381AB25F9300E9347C /* Pager.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
C8B7D1301AB25F9300E9347C /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftMigration = 0720;
LastSwiftUpdateCheck = 0720;
LastUpgradeCheck = 0920;
ORGANIZATIONNAME = Cheesecake;
TargetAttributes = {
C8B7D1371AB25F9300E9347C = {
CreatedOnToolsVersion = 6.1.1;
LastSwiftMigration = 0920;
};
};
};
buildConfigurationList = C8B7D1331AB25F9300E9347C /* Build configuration list for PBXProject "Pager" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = C8B7D12F1AB25F9300E9347C;
productRefGroup = C8B7D1391AB25F9300E9347C /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
C8B7D1371AB25F9300E9347C /* Pager */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
C8B7D1361AB25F9300E9347C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C8B7D1431AB25F9300E9347C /* Main.storyboard in Resources */,
C8B7D1481AB25F9300E9347C /* LaunchScreen.xib in Resources */,
C8B7D1451AB25F9300E9347C /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
C82DD78F1D95C0F200CF596E /* Swift lint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Swift lint";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
C8B7D1341AB25F9300E9347C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C876EF5F2042364400701C03 /* PagerController.swift in Sources */,
C8B7D1401AB25F9300E9347C /* ViewController.swift in Sources */,
C876EF63204236A500701C03 /* TabView.swift in Sources */,
C8B7D13E1AB25F9300E9347C /* AppDelegate.swift in Sources */,
C876EF612042366800701C03 /* Utils.swift in Sources */,
C2652A591C9E894D00FE8F50 /* Extensions.swift in Sources */,
C8E736D71D92CAD5001491E6 /* GreyDetailViewController.swift in Sources */,
C8E736D81D92CAD5001491E6 /* GreyViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
C8B7D1411AB25F9300E9347C /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
C8B7D1421AB25F9300E9347C /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
C8B7D1461AB25F9300E9347C /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
C8B7D1471AB25F9300E9347C /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
C8B7D1551AB25F9300E9347C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
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_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_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";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
C8B7D1561AB25F9300E9347C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
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_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_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";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
C8B7D1581AB25F9300E9347C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Pager/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.ckl.pager;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
C8B7D1591AB25F9300E9347C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Pager/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.ckl.pager;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
C8B7D1331AB25F9300E9347C /* Build configuration list for PBXProject "Pager" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C8B7D1551AB25F9300E9347C /* Debug */,
C8B7D1561AB25F9300E9347C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C8B7D1571AB25F9300E9347C /* Build configuration list for PBXNativeTarget "Pager" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C8B7D1581AB25F9300E9347C /* Debug */,
C8B7D1591AB25F9300E9347C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = C8B7D1301AB25F9300E9347C /* Project object */;
}
================================================
FILE: Pager.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Pager.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: PagerTests/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
================================================
FILE: PagerTests/PagerTests.swift
================================================
//
// PagerTests.swift
// PagerTests
//
// Created by Lucas Oceano on 12/03/2015.
// Copyright (c) 2015 Cheesecake. All rights reserved.
//
import UIKit
import XCTest
class PagerTests: XCTestCase {
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
XCTAssert(true, "Pass")
}
func testPerformanceExample() {
// This is an example of a performance test case.
}
}
================================================
FILE: README.md
================================================
[](http://swift.org)
Pager is the simplest and best way to implement sliding view controllers.
## Installation
Drop in the Spring folder to your Xcode project.
Or via CocoaPods pre-release:
```CocoaPods
platform :ios, '8.0'
pod 'Pager'
use_frameworks!
```
## Usage
Subclass PagerController (as it's a `UIViewController` subclass) and implement data source methods in the subclass.
#### Usage with Code
```Swift
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
}
```
## Data Source
```Swift
func numberOfTabs(pager: PagerController) -> Int
func tabViewForIndex(index: Int, pager: PagerController) -> UIView
optional func viewForTabAtIndex(index: Int, pager: PagerController) -> UIView
optional func controllerForTabAtIndex(index: Int, pager: PagerController) -> UIViewController
```
## Delegate
```Swift
optional func didChangeTabToIndex(pager: PagerController, index: Int)
optional func didChangeTabToIndex(pager: PagerController, index: Int, previousIndex: Int)
optional func didChangeTabToIndex(pager: PagerController, index: Int, previousIndex: Int, swipe: Bool)
```
## Contact
- [Lucas Farah](mailto:lucas.farah@me.com) - [@7farah7](http://twitter.com/7farah7)
- [Lucas Martins](mailto:lucoceano@gmail.com) - [lucoceano.com](http://www.lucoceano.com)
Pager is a port from [CKViewPager](https://github.com/lucoceano/CKViewPager) to swift.
## Licence
Pager is MIT licensed. See the LICENCE file for more info.
gitextract_q9l42mii/ ├── .gitignore ├── .swift-version ├── .swiftlint.yml ├── LICENSE ├── Pager/ │ ├── AppDelegate.swift │ ├── Base.lproj/ │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Extensions.swift │ ├── GreyDetailViewController.swift │ ├── GreyViewController.swift │ ├── Images.xcassets/ │ │ └── AppIcon.appiconset/ │ │ └── Contents.json │ ├── Info.plist │ ├── ViewController.swift │ └── library/ │ ├── PagerController.swift │ ├── TabView.swift │ └── Utils.swift ├── Pager.podspec ├── Pager.xcodeproj/ │ ├── project.pbxproj │ └── project.xcworkspace/ │ └── contents.xcworkspacedata ├── PagerTests/ │ ├── Info.plist │ └── PagerTests.swift └── README.md
Condensed preview — 22 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (83K chars).
[
{
"path": ".gitignore",
"chars": 1108,
"preview": "# Created by .ignore support plugin (hsz.mobi)\n### Swift template\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n"
},
{
"path": ".swift-version",
"chars": 2,
"preview": "3\n"
},
{
"path": ".swiftlint.yml",
"chars": 189,
"preview": "disabled_rules:\n - line_length\n - type_name\n - weak_delegate\n\nforce_cast: warning\n\nfunction_body_length:\n - 108\n - "
},
{
"path": "LICENSE",
"chars": 1077,
"preview": "Copyright (c) 2014-2015 Meng To (meng@designcode.io)\n\nPermission is hereby granted, free of charge, to any person obtain"
},
{
"path": "Pager/AppDelegate.swift",
"chars": 1521,
"preview": "//\n// AppDelegate.swift\n// Pager\n//\n// Created by Lucas Oceano on 12/03/2015.\n// Copyright (c) 2015 Cheesecake. All "
},
{
"path": "Pager/Base.lproj/LaunchScreen.xib",
"chars": 2625,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
},
{
"path": "Pager/Base.lproj/Main.storyboard",
"chars": 15381,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "Pager/Extensions.swift",
"chars": 1140,
"preview": "//\n// Extensions.swift\n// Pager\n//\n// Created by Lucas Farah on 3/20/16.\n// Copyright © 2016 Cheesecake. All rights "
},
{
"path": "Pager/GreyDetailViewController.swift",
"chars": 356,
"preview": "//\n// GreyDetailViewController.swift\n// Pager\n//\n// Created by Antonio Alves on 8/16/16.\n// Copyright © 2016 Cheesec"
},
{
"path": "Pager/GreyViewController.swift",
"chars": 1181,
"preview": "//\n// GreyViewController.swift\n// Pager\n//\n// Created by Antonio Alves on 8/16/16.\n// Copyright © 2016 Cheesecake. A"
},
{
"path": "Pager/Images.xcassets/AppIcon.appiconset/Contents.json",
"chars": 585,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"iphone\",\n \"size\" : \"29x29\",\n \"scale\" : \"2x\"\n },\n {\n \"idiom\""
},
{
"path": "Pager/Info.plist",
"chars": 1346,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "Pager/ViewController.swift",
"chars": 2460,
"preview": "//\n// ViewController.swift\n// Pager\n//\n// Created by Lucas Oceano on 12/03/2015.\n// Copyright (c) 2015 Cheesecake. A"
},
{
"path": "Pager/library/PagerController.swift",
"chars": 26429,
"preview": "//\n// ViewPager.swift\n// Pager\n//\n// Created by Lucas Oceano on 12/03/2015.\n// Copyright (c) 2015 Cheesecake. All ri"
},
{
"path": "Pager/library/TabView.swift",
"chars": 294,
"preview": "import UIKit\n\nclass TabView: UIView {\n\n override init(frame: CGRect) {\n super.init(frame: frame)\n self."
},
{
"path": "Pager/library/Utils.swift",
"chars": 920,
"preview": "import UIKit\n\nextension Array {\n func find(_ includedElement: (Element) -> Bool) -> Int? {\n for (idx, element)"
},
{
"path": "Pager.podspec",
"chars": 439,
"preview": "Pod::Spec.new do |s|\n s.name = 'Pager'\n s.version = '1.4.0'\n s.license = 'MIT'\n s.summary = 'Easily create sliding t"
},
{
"path": "Pager.xcodeproj/project.pbxproj",
"chars": 16287,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "Pager.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 150,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:Pager.xcodeproj"
},
{
"path": "PagerTests/Info.plist",
"chars": 733,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "PagerTests/PagerTests.swift",
"chars": 549,
"preview": "//\n// PagerTests.swift\n// PagerTests\n//\n// Created by Lucas Oceano on 12/03/2015.\n// Copyright (c) 2015 Cheesecake. "
},
{
"path": "README.md",
"chars": 1512,
"preview": "\n[](http://swift.org)\n\nPager is the simplest and best way t"
}
]
About this extraction
This page contains the full source code of the lucoceano/Pager GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 22 files (74.5 KB), approximately 21.4k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.