2016-01-27 68 views
0

好的我試圖在UIScrollView上添加SKSpriteNode,我該怎麼做?UIScrollView中的Swift SKSpritenodes

+0

可能的重複[如何添加滾動視圖到我的gameScene.swift,這將滾動一系列的精靈?](http://stackoverflow.com/questions/35000529/how-do-i-add -a-scroll-view-to-my-gamescene-swift-that-will-scroll-through-a-ser) – Knight0fDragon

回答

2

你到目前爲止嘗試過什麼? 作爲一般的堆棧溢出規則,如果您希望獲得幫助,您應該始終發佈代碼。

我建議始終從我的gitHub項目中獲取此代碼的最新版本incase我做了更改,因爲此答案,鏈接位於底部。

第1步:創建一個新的文件,迅速在這個代碼

import SpriteKit 

/// Scroll direction 
enum ScrollDirection { 
    case vertical // cases start with small letters as I am following Swift 3 guildlines. 
    case horizontal 
} 

class CustomScrollView: UIScrollView { 

// MARK: - Static Properties 

/// Touches allowed 
static var disabledTouches = false 

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

// MARK: - Properties 

/// Current scene 
private let currentScene: SKScene 

/// Moveable node 
private let moveableNode: SKNode 

/// Scroll direction 
private let scrollDirection: ScrollDirection 

/// Touched nodes 
private var nodesTouched = [AnyObject]() 

// MARK: - Init 
init(frame: CGRect, scene: SKScene, moveableNode: SKNode) { 
    self.currentScene = scene 
    self.moveableNode = moveableNode 
    self.scrollDirection = scrollDirection 
    super.init(frame: frame) 

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

    if scrollDirection == .horizontal { 
     let flip = CGAffineTransformMakeScale(-1,-1) 
     transform = flip 
    } 
} 

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?) { 

    for touch in touches { 
     let location = touch.locationInNode(currentScene) 

     guard !CustomScrollView.disabledTouches else { return } 

     /// Call touches began in current scene 
     currentScene.touchesBegan(touches, withEvent: event) 

     /// Call touches began in all touched nodes in the current scene 
     nodesTouched = currentScene.nodesAtPoint(location) 
     for node in nodesTouched { 
      node.touchesBegan(touches, withEvent: event) 
     } 
    } 
} 

/// Moved 
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { 

    for touch in touches { 
     let location = touch.locationInNode(currentScene) 

     guard !CustomScrollView.disabledTouches else { return } 

     /// Call touches moved in current scene 
     currentScene.touchesMoved(touches, withEvent: event) 

     /// Call touches moved in all touched nodes in the current scene 
     nodesTouched = currentScene.nodesAtPoint(location) 
     for node in nodesTouched { 
      node.touchesMoved(touches, withEvent: event) 
     } 
    } 
} 

/// Ended 
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { 

    for touch in touches { 
     let location = touch.locationInNode(currentScene) 

     guard !CustomScrollView.disabledTouches else { return } 

     /// Call touches ended in current scene 
     currentScene.touchesEnded(touches, withEvent: event) 

     /// Call touches ended in all touched nodes in the current scene 
     nodesTouched = currentScene.nodesAtPoint(location) 
     for node in nodesTouched { 
      node.touchesEnded(touches, withEvent: event) 
     } 
    } 
} 

/// Cancelled 
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) { 

    for touch in touches! { 
     let location = touch.locationInNode(currentScene) 

     guard !CustomScrollView.disabledTouches else { return } 

     /// Call touches cancelled in current scene 
     currentScene.touchesCancelled(touches, withEvent: event) 

     /// Call touches cancelled in all touched nodes in the current scene 
     nodesTouched = currentScene.nodesAtPoint(location) 
     for node in nodesTouched { 
      node.touchesCancelled(touches, withEvent: event) 
     } 
    } 
    } 
} 

// MARK: - Touch Controls 
extension CustomScrollView { 

    /// Disable 
    class func disable() { 
     CustomScrollView.scrollView?.userInteractionEnabled = false 
     CustomScrollView.disabledTouches = true 
    } 

    /// Enable 
    class func enable() { 
     CustomScrollView.scrollView?.userInteractionEnabled = true 
     CustomScrollView.disabledTouches = false 
    } 
} 

// MARK: - Delegates 
extension CustomScrollView: UIScrollViewDelegate { 

    func scrollViewDidScroll(scrollView: UIScrollView) { 

     if scrollDirection == .horizontal { 
      moveableNode.position.x = scrollView.contentOffset.x 
     } else { 
      moveableNode.position.y = scrollView.contentOffset.y 
     } 
    } 
} 

這使的UIScrollView的子類,並建立了它的基本屬性粘貼。它比自己的觸摸方法傳遞到相關的場景。

第二步:在您的相關場景,你想用它創建一個滾動視圖和可移動節點屬性,像這樣

weak var scrollView: CustomScrollView! 
let moveableNode = SKNode() 

和他們didMoveToView

scrollView = CustomScrollView(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height), scene: self, moveableNode: moveableNode, scrollDirection: .vertical) 
scrollView.contentSize = CGSizeMake(self.frame.size.width, self.frame.size.height * 2) 
view?.addSubview(scrollView) 


addChild(moveableNode) 

添加到場景什麼你在第1行中執行此操作是您使用場景尺寸初始化滾動視圖助手。您還可以沿着場景傳遞參考​​以及在步驟2中創建的moveableNode。 第2行是設置scrollView內容大小的位置,在這種情況下,它的長度是屏幕高度的兩倍。

第3步: - 添加標籤或節點等並定位它們。

label1.position.y = CGRectGetMidY(self.frame) - self.frame.size.height 
moveableNode.addChild(label1) 

在這個例子中,標籤將位於scrollView的第2頁。這是你不得不隨身攜帶標籤和定位的地方。

我建議如果你在滾動視圖中有很多頁面並且有很多標籤要做以下操作。在滾動視圖中爲每個頁面創建一個SKSpriteNode,並使它們都成爲屏幕的大小。將它們稱爲page1Node,page2Node等。然後將所需的所有標籤添加到page2Node中。這樣做的好處是,你基本上可以像往常一樣在page2Node中定位所有的東西,而不僅僅是在scrollView中定位page2Node。

你也很幸運,因爲使用垂直scrollView(你說你想要的),你不需要做任何翻轉和反向定位。

我做了一些類的func,所以如果你需要禁用你的scrollView incase你覆蓋scrollView的頂部的另一個菜單。

CustomScrollView.enable() 
CustomScrollView.disable() 

最後,在轉換到新的場景之前,請不要忘記從場景中移除滾動視圖。在spritekit中處理UIKit時的一個難題。

scrollView?.removeFromSuperView() 

How to create a vertical scrolling menu in spritekit?

https://github.com/crashoverride777/SwiftySKScrollView

+0

最好包括一些例子來說明你的類應該如何使用。大多數時候,這樣的答案(僅鏈接答案)被標記和刪除。 – Whirlwind

+0

我知道,但這是一個非常寬泛的問題,而不是一個關於特定位代碼的問題。示例代碼可能會變長 – crashoverride777

+0

建議使用源代碼,但只要問題針對的是不會導致廣義答案的特定問題,則代碼不必始終發佈。這個問題就是一個很好的例子。 OP有一個特定的問題,那就是:如何將'SKSpriteNode'添加到'UIScrollView'?只有幾種方法可以回答, – Knight0fDragon

2

您正在運行到我用了一段艱難的問題。根本的問題是你不能將SKNodes添加到UIKit視圖,並且你不能將UIKit視圖添加到SKNodes。視圖不是節點,節點不是視圖,很遺憾這不起作用。雖然您可以將UIKit元素添加到SKScene的視圖屬性,但儘可能採用它。在我終於明白之前,我在這方面掙扎了很長時間。

我仍然混合UIKit和SpriteKit,順便說一句,但我以有限的方式這樣做,它從不依賴於向視圖添加節點,反之亦然。

最好的辦法是創建一個與你需要的SKNode一樣大的SKNode,以保存所有的SKSpriteNodes,然後在touchesMoved:function期間調整其在屏幕上的位置。 (基本上創建您自己的基於SpriteKit的滾動視圖)。

1

您可以使用SKCameraNode以及比您的視口大的場景。這基本上是滾動視圖的SpriteKit版本。