1

I managed to get a scrollview working and scrolling, but now when I go to scroll it only scrolls from right to left and was wondering how I go about reversing it so it scrolls from left to right instead.

Here is my menu code that contains my scrollview:

var moveableNode = SKNode()
var scrollView: CustomScrollView!

private var spriteSize = CGSize.zero

let kMargin: CGFloat = 40

var sprite = SKSpriteNode()

class Menu: SKScene {


override func didMoveToView(view: SKView) {


    addChild(moveableNode)

    spriteSize = SKSpriteNode (imageNamed: "card_level01").size

    let initialMargin = size.width/2
    let marginPerImage = kMargin + spriteSize.width

    scrollView = CustomScrollView(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height), scene: self, moveableNode: moveableNode)

    scrollView.contentSize = CGSizeMake(initialMargin*2 + (marginPerImage * 7), size.height)

    // scrollView.contentSize = CGSizeMake(self.frame.size.width * 2, self.frame.size.height)
    view.addSubview(scrollView)


    for i in 1...8 {

        let sprite = SKSpriteNode(imageNamed: String(format: "card_level%02d", i))
        sprite.position = CGPoint (x: initialMargin + (marginPerImage * (CGFloat(i) - 1)), y: size.height / 2)
        moveableNode.addChild(sprite)

    }

Here is my scrollView Class that is a subclass of UIScrollView:

 var nodesTouched: [AnyObject] = [] // global

class CustomScrollView: UIScrollView {

// MARK: - Static Properties

/// Touches allowed
static var disabledTouches = false

/// Scroll view
private static var scrollView: UIScrollView!

private static var contentView: UIView!
// MARK: - Properties

/// Current scene
private var currentScene: SKScene?

/// Moveable node
private var moveableNode: SKNode?

// MARK: - Init
init(frame: CGRect, scene: SKScene, moveableNode: SKNode) {
    print("Scroll View init")
    super.init(frame: frame)

    CustomScrollView.scrollView = self
    currentScene = scene
    self.moveableNode = moveableNode
    self.frame = frame
    indicatorStyle = .White
    scrollEnabled = true
    //self.minimumZoomScale = 1
    //self.maximumZoomScale = 3
    canCancelContentTouches = false
    userInteractionEnabled = true
    delegate = self

    //flip for spritekit (only needed for horizontal)
    let verticalFlip = CGAffineTransformMakeScale(-1,-1)
    self.transform = verticalFlip

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


 }

  // MARK: - Touches
 extension CustomScrollView {

/// began
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    print("Touch began scroll view")

    guard !CustomScrollView.disabledTouches else { return }
    currentScene?.touchesBegan(touches, withEvent: event)
    }

/// moved
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    print("Touch moved scroll view")

    guard !CustomScrollView.disabledTouches else { return }
    currentScene?.touchesMoved(touches, withEvent: event)
}

/// ended
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    print("Touch ended scroll view")

    guard !CustomScrollView.disabledTouches else { return }
    currentScene?.touchesEnded(touches, withEvent: event)
}

/// cancelled
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
    print("Touch cancelled scroll view")

    guard !CustomScrollView.disabledTouches else { return }
    currentScene?.touchesCancelled(touches, withEvent: event)
   }
 }

 // MARK: - Touch Controls
extension CustomScrollView {

/// Disable
class func disable() {
    print("Disabled scroll view")
    CustomScrollView.scrollView?.userInteractionEnabled = false
    CustomScrollView.disabledTouches = true
}

/// Enable
class func enable() {
    print("Enabled scroll view")
    CustomScrollView.scrollView?.userInteractionEnabled = true
    CustomScrollView.disabledTouches = false
  }
}

// MARK: - Delegates
extension CustomScrollView: UIScrollViewDelegate {

/// did scroll
func scrollViewDidScroll(scrollView: UIScrollView) {
    print("Scroll view did scroll")

   moveableNode!.position.x = scrollView.contentOffset.x // Left/Right

   //moveableNode!.position.y = scrollView.contentOffset.y // Up/Dowm
   }


}
Astrum
  • 375
  • 6
  • 21

1 Answers1

2

You need get my updated helper on gitHub (v1.1) first before reading the rest.

My helper only really works well when your scene scale mode (gameViewController) is set to

.ResizeFill

so your scenes do not crop. If you use a different scaleMode such as

.AspectFill 

than it might crop stuff in your scrollView which you would need to adjust for.

It also doesnt work if your game/app supports both portrait and landscape, which is unlikely for a game anyway.

So as I said and you have also noticed when using a ScrollView in spriteKit the coordinates are different compared to UIKit. For vertical scrolling this doesn't really mean anything, but for horizontal scrolling everything it is in reverse. So to fix this you do the following

Set up your scrollView for horizontal scrolling, passing along the new scrollDirection property (.Horizontal in this case)

scrollView = CustomScrollView(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height), scene: self, moveableNode: moveableNode, scrollDirection: .Horizontal)
scrollView.contentSize = CGSizeMake(self.frame.size.width * 3, self.frame.size.height) // * 3 makes it twice as wide as screen
view.addSubview(scrollView)

you need to also add this line of code after adding it to the view.

scrollView.setContentOffset(CGPoint(x: 0 + self.frame.size.width * 2, y: 0), animated: true)

this is the line you use to tell the ScrollView on which page to start. Now in this example the scrollView is three times as wide as the screen, therefore you need to offset the content by 2 screen lengths

Now to make things easier for positioning I would do this, create sprites for each page of the scrollView. This makes positioning much easier later on.

let page1ScrollView = SKSpriteNode(color: SKColor.clearColor(), size: CGSizeMake(self.frame.size.width, self.frame.size.height))
page1ScrollView.position = CGPointMake(CGRectGetMidX(self.frame) - (self.frame.size.width * 2), CGRectGetMidY(self.frame))
moveableNode.addChild(page1ScrollView)

let page2ScrollView = SKSpriteNode(color: SKColor.clearColor(), size: CGSizeMake(self.frame.size.width, self.frame.size.height))
page2ScrollView.position = CGPointMake(CGRectGetMidX(self.frame) - (self.frame.size.width), CGRectGetMidY(self.frame))
moveableNode.addChild(page2ScrollView)

let page3ScrollView = SKSpriteNode(color: SKColor.clearColor(), size: CGSizeMake(self.frame.size.width, self.frame.size.height))
page3ScrollView.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
moveableNode.addChild(page3ScrollView)

and now you can positioning your actual labels, sprites much easier.

/// Test label page 1
let myLabel = SKLabelNode(fontNamed:"Chalkduster")
myLabel.text = "Hello, World!"
myLabel.fontSize = 45
myLabel.position = CGPointMake(0, 0)
page1ScrollView.addChild(myLabel)

/// Test sprite page 2
let sprite = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 50, height: 50))
sprite.position = CGPointMake(0, 0)
page2ScrollView.addChild(sprite)

/// Test sprite page 3
let sprite2 = SKSpriteNode(color: SKColor.blueColor(), size: CGSize(width: 50, height: 50))
sprite2.position = CGPointMake(0, 0)
page3ScrollView.addChild(sprite2)

Hope this helps.

I also updated my GitHub project to explain this better

https://github.com/crashoverride777/Swift2-SpriteKit-UIScrollView-Helper

crashoverride777
  • 10,581
  • 2
  • 32
  • 56
  • Thanks I am currently half asleep checking this but I will look at it tomorrow. If you have more time (and if your not sick of me asking questions) then could you have a look at this problem. http://stackoverflow.com/questions/34801518/sprite-moves-two-places-after-being-paused-and-then-unpaused – Astrum Jan 15 '16 at 14:38
  • cool, i just updated the answer again, and I also made some slight changes to my helper. Its all properly explained on gitHub https://github.com/crashoverride777/Swift2-SpriteKit-UIScrollView-Helper – crashoverride777 Jan 15 '16 at 15:13
  • I just posted an answer to your other question too. – crashoverride777 Jan 15 '16 at 15:39
  • I have just implemented it and now it works completely fine I understand completely now and thank you. I might run into a few more troubles down the road but if so i'll just ask another question. Thanks again. – Astrum Jan 16 '16 at 05:52
  • My pleasure, happy coding – crashoverride777 Jan 16 '16 at 09:58
  • cash, I have come to the conclusion that the pages in the scrollview that you gave me are too annoying to scroll through every time I want to look for a sprite. So i have asked another question. If you wouldn't mind taking a look at it for me I would be extremely grateful. Thanks. http://stackoverflow.com/questions/34849615/swift-2-0-spritekit-scrollview-to-not-use-pages – Astrum Jan 18 '16 at 07:57
  • Ill have a look in a bit – crashoverride777 Jan 18 '16 at 13:06
  • so what do you think? is it possible? – Astrum Jan 19 '16 at 00:54
  • I just answered the other question, not really sure what you are asking – crashoverride777 Jan 19 '16 at 11:51