Swiftpack.co - Package - crashoverride777/swifty-sk-scroll-view

SwiftySKScrollView

Swift 5.0 Platform CocoaPods Compatible

A helper class to add a UIScrollView to your SpriteKit scenes.

The helper will automatically forward button presses to the relevant SKScene and node subclasses.

Please Read

In general it is not good practice to add UIKit elements to SpriteKit games, all your UI should be done using SpriteKit APIs (SKSpriteNodes, SKLabelNodes, SKNodes etc) directly in the relevant SKScene(s). However there are a few things in UIKit, UIScrollViews and UICollectionViews in particular, that would be quite difficult to recreate with SpriteKit APIs.

This is also an older project I actually no longer use in my own apps as it is not the most elegant solution in world to achieve a scrollable list. It should only be used for very small things such as a character select menus.

It is much better to use a UICollectionView for a scrollable list due to cell reusage end efficiency. You can subclass UICollectionViews in similar fashion than this helper.

I will continue to maintain this repositiory indefinately.

Requirements

  • iOS 10.3+
  • Swift 5.0+

Installation

Cocoa Pods

CocoaPods is a dependency manager for Cocoa projects. Simply install the pod by adding the following line to your pod file

pod 'SwiftySKScrollView'

There is now an app which makes handling pods much easier

Altenatively you can drag the swift file(s) manually into your project.

Swift Package Manager

The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler.

To add a swift package to your project simple open your project in xCode and click File > Swift Packages > Add Package Dependency. Than enter https://github.com/crashoverride777/swifty-sk-scroll-view as the repository URL and finish the setup wizard.

Alternatively if you have a Framwork that requires adding SwiftySKScrollView as a dependency is as easy as adding it to the dependencies value of your Package.swift.

dependencies: [
.package(url: "https://github.com/crashoverride777/swifty-sk-scroll-view.git", from: "2.4.0")
]

Manually

Add the SwiftySKScrollView.swift file to your project

Usage

  • Add the import statement when using CocoaPods or SwiftPackageManager
import SwiftySKScrollView 
  • In your relevant SKScene you want to use it you create those 2 properties
class MenuScene: SKScene {
    var scrollView: SwiftySKScrollView?
    let moveableNode = SKNode()
    ...
}
  • Set up the properties from step above.

In didMoveToView add the moveable node

addChild(moveableNode)

and set up the scrollView

Vertical scrolling

scrollView = SwiftySKScrollView(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height), moveableNode: moveableNode, direction: .vertical)
scrollView?.contentSize = CGSize(width: scrollView!.frame.width, height: scrollView!.frame.height * 3) // makes it 3 times the height
view?.addSubview(scrollView!)

Horizontal scrolling

scrollView = SwiftySKScrollView(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height), moveableNode: moveableNode, direction: .horizontal)
scrollView?.contentSize = CGSize(width: scrollView!.frame.width * 3, height: scrollView!.frame.height) // * 3 makes it three times as wide
view?.addSubview(scrollView!)
scrollView?.setContentOffset(CGPoint(x: 0 + scrollView!.frame.width * 2, y: 0), animated: true)

Line 1 inits the helper with your scene dimensions. You also pass along the moveableNode you created at step 2 and the scrollDirection you want.

Line 2 is where you set up the content size of the scrollView.

Line 3 adds the scrollView

Line 4 (horizontal) resets the contentOffset so you start from left to right (UIKit coordinates are different to SpriteKits).

  • Add sprites for each page in the scrollView to make positioning your actual stuff later on much easier

Vertical scrolling

guard let scrollView = scrollView else { return } // unwrap  optional 

let page1ScrollView = SKSpriteNode(color: .clear, size: CGSize(width: scrollView.frame.width, height: scrollView.frame.size.height))
page1ScrollView.position = CGPoint(x: frame.midX, y: frame.midY)
moveableNode.addChild(page1ScrollView)
        
let page2ScrollView = SKSpriteNode(color: .clear, size: CGSize(width: scrollView.frame.width, height: scrollView.frame.size.height))
page2ScrollView.position = CGPoint(x: frame.midX, y: frame.midY - scrollView.frame.height)
moveableNode.addChild(page2ScrollView)
        
let page3ScrollView = SKSpriteNode(color: .clear, size: CGSize(width: scrollView.frame.width, height: scrollView.frame.size.height))
page3ScrollView.position = CGPoint(x: frame.midX, y: frame.midY - (scrollView.frame.height * 2))
moveableNode.addChild(page3ScrollView)

Horizontal scrolling (positioning is in reverse)

guard let scrollView = scrollView else { return } // unwrap  optional 

let page1ScrollView = SKSpriteNode(color: .clear, size: CGSize(width: scrollView.frame.width, height: scrollView.frame.size.height))
page1ScrollView.position = CGPoint(x: frame.midX - (scrollView.frame.width * 2), y: frame.midY)
moveableNode.addChild(page1ScrollView)
        
let page2ScrollView = SKSpriteNode(color: .clear, size: CGSize(width: scrollView.frame.width, height: scrollView.frame.size.height))
page2ScrollView.position = CGPoint(x: frame.midX - (scrollView.frame.width), y: frame.midY)
moveableNode.addChild(page2ScrollView)
        
let page3ScrollView = SKSpriteNode(color: .clear, size: CGSize(width: scrollView.frame.width, height: scrollView.frame.size.height))
page3ScrollView.zPosition = -1
page3ScrollView.position = CGPoint(x: frame.midX, y: frame.midY)
moveableNode.addChild(page3ScrollView)
  • Add your sprites, labels etc. Because you will add them to the above sprites you can position them as usual which is why its much easier to do Step 4 first.

Vertical scrolling


/// Test sprites page 1
let sprite1Page1 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite1Page1.position = CGPoint(x: 0, y: 0)
page1ScrollView.addChild(sprite1Page1)
        
let sprite2Page1 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite2Page1.position = CGPoint(x: sprite1Page1.position.x, y: sprite1Page1.position.y - sprite2Page1.size.height * 1.5)
sprite1Page1.addChild(sprite2Page1)
        
/// Test sprites page 2
let sprite1Page2 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite1Page2.position = CGPoint(x: 0, y: 0)
page2ScrollView.addChild(sprite1Page2)
        
let sprite2Page2 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite2Page2.position = CGPoint(x: sprite1Page2.position.x, y: sprite1Page2.position.y - (sprite2Page2.size.height * 1.5))
sprite1Page2.addChild(sprite2Page2)
        
/// Test sprites page 3
let sprite1Page3 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite1Page3.position = CGPoint(x: 0, y: 0)
page3ScrollView.addChild(sprite1Page3)
        
let sprite2Page3 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite2Page3.position = CGPoint(x: sprite1Page3.position.x, y: sprite1Page3.position.y - (sprite2Page3.size.height * 1.5))
sprite1Page3.addChild(sprite2Page3)

Horizontal

/// Test sprites page 1
let sprite1Page1 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite1Page1.position = CGPoint(x: 0, y: 0)
page1ScrollView.addChild(sprite1Page1)
        
let sprite2Page1 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite2Page1.position = CGPoint(x: sprite1Page1.position.x + (sprite2Page1.size.width * 1.5), y: sprite1Page1.position.y)
sprite1Page1.addChild(sprite2Page1)
        
/// Test sprites page 2
let sprite1Page2 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite1Page2.position = CGPoint(x: 0, y: 0)
page2ScrollView.addChild(sprite1Page2)
        
let sprite2Page2 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite2Page2.position = CGPoint(x: sprite1Page2.position.x + (sprite2Page2.size.width * 1.5), y: sprite1Page2.position.y)
sprite1Page2.addChild(sprite2Page2)
        
/// Test sprites page 3
let sprite1Page3 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite1Page3.position = CGPoint(x: 0, y: 0)
page3ScrollView.addChild(sprite1Page3)
        
let sprite2Page3 = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite2Page3.position = CGPoint(x: sprite1Page3.position.x + (sprite2Page3.size.width * 1.5), y: sprite1Page3.position.y)
sprite1Page3.addChild(sprite2Page3)
  • If you need to disable your scrollView incase you overlay another menu ontop of the scrollView or if you pressed a button you can use the isDisabled bool. Remember, UIKit elements get added to your GameViewController and not your SKScenes, so you will have to play around here and see how your SpriteKit UI interacts with the scrollView.
scrollView?.isDisabled = true
  • Finally do not forget to remove the scroll view from your scene before transitioning to a new one. As mentioned above one of the pains when dealing with UIKit in SpriteKit. Its best done in WillMoveFromView
override func willMove(from view: SKView) {
    scrollView?.removeFromSuperview()
    scrollView = nil // nil out reference to deallocate properly
}

Github

link
Stars: 50

Dependencies

Used By

Total: 0

Releases

Cleanup - 2020-02-23 13:23:28

Project folder cleanup

Swift Package Manager - 2020-02-08 14:19:59

Add support for Swift Package Manager

Bugfixes - 2019-09-13 21:52:21

Swift 5 - 2019-03-27 19:18:05

  • Updated to Swift 5
  • Set min deployment target to 10.3

SwiftySKScrollView - 2018-09-16 14:20:50

Updated to Swift 4.2

SwiftySKScrollView - 2018-03-03 16:16:41

Cleanup

SwiftySKScrollView - 2017-10-11 20:09:02

Removed static properties Sample project cleanup Small changes to setup, please check instructions again

Know Issues:

There is a problem with the scroll indicators positioning, so they are hidden for this release. Will fix ASAP

SwiftySKScrollView - 2017-09-24 14:35:26

Swift 4 update

SwiftySKScrollView - 2017-02-01 22:48:00

Cleanup

SwiftySKScrollView - 2016-10-03 17:46:24

Project has been renamed to SwiftySKScrollView.

No more source breaking changes after this update. All future changes will be handled with deprecated messages.

Swift-SpriteKitScrollView - 2016-09-25 13:59:28

Cleanup and documentation fixes

The static touch control methods are now called

CustomScrollView.enableTouches()
CustomScrollView.disableTouches()

Swift-SpriteKitScrollView - 2016-09-09 00:11:06

Updated to Swift 3.

Swift-SpriteKitScrollView - 2016-08-14 21:03:21

Cleanup

Swift-SpriteKit-UIScrollView-Helper - 2016-07-09 22:06:20

  • Small improvements

Swift-SpriteKit-UIScrollView-Helper - 2016-06-23 11:44:26

Clean-up

Swift-SpriteKit-UIScrollView-Helper - 2016-03-19 14:26:54

Fixed an issue that could cause a crash when changing scenes.

Please change this line in the helper

  private unowned let: SKScene

to

  private let: SKScene

Swift2-SpriteKit-UIScrollView-Helper - 2016-03-13 19:54:34

Moved the method to forward button presses on nodes into the helper so there is no more need to implement it in the gameScene. Please update your helper and remove the methods in your touches method that used the nodesTouched array in the helper (should show as error)

Other small fixes and improvements.

Swift2-SpriteKit-UIScrollView-Helper - 2016-02-04 16:01:09

Clean-up

Swift2-SpriteKit-UIScrollView-Helper - 2016-01-19 12:49:03

Updated sample project to show how to add more sprites to the same scrollView page.

Swift2-SpriteKit-UIScrollView-Helper - 2016-01-15 15:04:38

Small improvements to make it easier to select vertical or horizontal scrolling without having to manually adjust settings in the helper.

Swift2 CustomScrollView Helper SpriteKit - 2016-01-09 22:09:16