Skip to content

Instantly share code, notes, and snippets.

@Ridwy
Created June 21, 2015 15:19
Show Gist options
  • Save Ridwy/e515b2161520d4be717a to your computer and use it in GitHub Desktop.
Save Ridwy/e515b2161520d4be717a to your computer and use it in GitHub Desktop.
//
// ScrollPageController.swift
// ScrollPageController
//
// Created by Chiharu Nameki on 2015/06/21.
// Copyright (c) 2015 Chiharu Nameki. All rights reserved.
//
import UIKit
class ScrollPageController: UIViewController {
private var pages: [UIView?] = [] // viewControllersのview, 貼り付けていない場合はnil
var viewControllers: [UIViewController] = [] {
willSet {
for (index, _) in enumerate(viewControllers) {
hideViewControllerAtIndex(index)
}
}
didSet {
pages = []
for _ in viewControllers {
pages.append(nil)
}
selectedIndex = 0
setupScrollView()
}
}
private(set) var selectedIndex: Int = 0
var selectedViewController: UIViewController {
return viewControllers[selectedIndex]
}
func selectViewControllerAtIndex(index: Int) {
selectedIndex = index
scrollView.bounds = frameOfPageAtIndex(selectedIndex)
}
var scrollView: UIScrollView! {
return view as! UIScrollView
}
override func loadView() {
let scrollView = UIScrollView(frame: UIScreen.mainScreen().bounds)
scrollView.pagingEnabled = true
view = scrollView
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
scrollView.addObserver(self, forKeyPath: "frame", options: .Initial | .New, context: nil)
scrollView.addObserver(self, forKeyPath: "bounds", options: .Initial | .New, context: nil)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
scrollView.removeObserver(self, forKeyPath: "frame")
scrollView.removeObserver(self, forKeyPath: "bounds")
}
override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
if keyPath == "frame" {
setupScrollView()
} else if keyPath == "bounds" {
layoutPages()
selectedIndex = Int(scrollView.bounds.midX / scrollView.bounds.size.width)
}
}
private func setupScrollView() {
let pageSize = scrollView.bounds.size
scrollView.contentSize.height = pageSize.height
scrollView.contentSize.width = pageSize.width * CGFloat(viewControllers.count)
scrollView.bounds = frameOfPageAtIndex(selectedIndex)
}
private func layoutPages() {
let pageSize = scrollView.bounds.size
let startIndex = Int(scrollView.bounds.minX / pageSize.width)
let endIndex = Int(scrollView.bounds.maxX / pageSize.width)
for (index, page) in enumerate(pages) {
if startIndex ... endIndex ~= index {
showViewControllerAtIndex(index)
} else {
hideViewControllerAtIndex(index)
}
}
}
private func hideViewControllerAtIndex(index: Int) {
if let page = pages[index] {
let controller = viewControllers[index]
controller.willMoveToParentViewController(nil)
controller.view.removeFromSuperview()
controller.removeFromParentViewController()
pages[index] = nil
}
}
private func showViewControllerAtIndex(index: Int) {
if let page = pages[index] {
page.frame = frameOfPageAtIndex(index)
} else {
let controller = viewControllers[index]
addChildViewController(controller)
controller.view.frame = frameOfPageAtIndex(index)
view.addSubview(controller.view)
controller.didMoveToParentViewController(self)
pages[index] = controller.view
}
}
private func frameOfPageAtIndex(index: Int) -> CGRect {
var pageFrame = scrollView.bounds
pageFrame.origin.x = scrollView.bounds.size.width * CGFloat(index)
return pageFrame
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment