Skip to content

Instantly share code, notes, and snippets.

@simondec
Last active December 26, 2020 12:54
Show Gist options
  • Save simondec/57a1ad9ef02bb50def8b to your computer and use it in GitHub Desktop.
Save simondec/57a1ad9ef02bb50def8b to your computer and use it in GitHub Desktop.
Recreating something similar to a UIPageViewController with a UIScrollView.
//
// ScrollableViewController.swift
//
import UIKit
class ScrollableViewController: UIViewController, UIScrollViewDelegate {
private let scrollView = UIScrollView()
private var controllers: Array<ViewController> = [
ViewController(color: UIColor.yellowColor()),
ViewController(color: UIColor.redColor()),
ViewController(color: UIColor.blueColor()),
ViewController(color: UIColor.yellowColor()),
ViewController(color: UIColor.redColor()),
ViewController(color: UIColor.blueColor())]
private var isDragging = false
override func loadView() {
self.automaticallyAdjustsScrollViewInsets = false
scrollView.delegate = self
scrollView.backgroundColor = UIColor.whiteColor()
scrollView.showsHorizontalScrollIndicator = true
scrollView.decelerationRate = UIScrollViewDecelerationRateFast
self.view = scrollView
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Scroll", style: UIBarButtonItemStyle.Plain, target: self, action: "didTapBarButton")
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let width: CGFloat = CGFloat(controllers.count) * self.view.bounds.size.width
scrollView.contentSize = CGSizeMake(width, self.view.bounds.size.height)
layoutViewController(0, toIndex: 0)
}
func scrollViewDidScroll(scrollView: UIScrollView) {
let fromIndex = floor(scrollView.bounds.origin.x / scrollView.bounds.size.width)
let toIndex = floor((CGRectGetMaxX(scrollView.bounds) - 1) / scrollView.bounds.size.width)
layoutViewController(Int(fromIndex), toIndex: Int(toIndex))
}
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
isDragging = true
}
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let offset = round(targetContentOffset.memory.x / self.view.bounds.size.width) * self.view.bounds.size.width
targetContentOffset.memory.x = offset
isDragging = false
}
func didTapBarButton() {
// Scroll mid-view
scrollView.setContentOffset(CGPointMake(2.5 * self.view.bounds.size.width, 0), animated: true)
}
private func layoutViewController(fromIndex: Int, toIndex: Int) {
for var i = 0; i < controllers.count; i++ {
// Remove views that should not be visible anymore
if (controllers[i].view.superview != nil && (i < fromIndex || i > toIndex)) {
println(NSString(format: "Hiding view controller at index: %i", i))
controllers[i].willMoveToParentViewController(nil)
controllers[i].view.removeFromSuperview()
controllers[i].removeFromParentViewController()
}
// Add views that are now visible
if (controllers[i].view.superview == nil && (i >= fromIndex && i <= toIndex)) {
println(NSString(format: "Showing view controller at index: %i", i))
var viewFrame = self.view.bounds
viewFrame.origin.x = CGFloat(i) * self.view.bounds.size.width
controllers[i].view.frame = viewFrame
self.addChildViewController(controllers[i])
scrollView.addSubview(controllers[i].view)
controllers[i].didMoveToParentViewController(self)
}
}
}
}
//
// ViewController.swift
//
import UIKit
class ViewController: UIViewController {
var color: UIColor?
init(color: UIColor?) {
super.init(nibName: nil, bundle: nil)
self.color = color
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = color
}
}
@steffimueller
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment