SwiftySKScrollView
一个辅助类,用于将 UIScrollView 添加到您的 SpriteKit 场景中。
辅助类将自动将按钮点击事件转发到相关的 SKScene 和节点子类。
请阅读
通常,将 UIKit 元素添加到 SpriteKit 游戏中并不是一个好的实践,您应该使用 SpriteKit API(SKSpriteNodes、SKLabelNodes、SKNodes 等)在相关的 SKScene 中直接完成所有 UI 制作。然而,UIKit 中有几个东西,特别是 UIScrollViews 和 UICollectionViews,使用 SpriteKit API 想要复现会比较困难。
这是一个较老的项目,实际上我已经不再在我的应用程序中使用它,因为它不是在世界上实现可滚动列表的最优雅的解决方案。它仅应用于非常小的内容,例如角色选择菜单。
由于单元格的重用和效率,使用 UICollectionView 来实现可滚动列表要更好。您可以用与这个辅助类类似的方式来创建 UICollectionViews 的子类。
我将无限期地维护这个仓库。
需求
- iOS 10.3+
- Swift 5.0+
安装
Cocoa Pods
CocoaPods是一个用于Cocoa项目的依赖管理器。只需将以下行添加到您的Podfile中即可安装pod:
pod 'SwiftySKScrollView'
现在有一个app,它使处理pod变得更容易
或者,您也可以手动将swift文件拖入您的项目。
Swift Package Manager
Swift Package Manager是一个用于自动分发Swift代码的工具,它集成到Swift编译器中。
要将swift包添加到您的项目中,只需在XCode中打开项目,然后点击File > Swift Packages > Add Package Dependency。然后输入https://github.com/crashoverride777/swifty-sk-scroll-view
作为存储库URL,并完成设置向导。
或者,如果您有一个需要在Package.swift的依赖项值中添加SwiftySKScrollView的框架,只需将其添加到依赖项值中即可。
dependencies: [
.package(url: "https://github.com/crashoverride777/swifty-sk-scroll-view.git", from: "2.4.0")
]
手动安装
将SwiftySKScrollView.swift文件添加到您的项目中
使用说明
- 当使用CocoaPods或SwiftPackageManager时,请添加导入语句
import SwiftySKScrollView
- 在您想使用它的相关SKScene中,创建这两个属性
class MenuScene: SKScene {
var scrollView: SwiftySKScrollView?
let moveableNode = SKNode()
...
}
- 设置上述步骤中的属性。
在didMoveToView中添加可移动节点
addChild(moveableNode)
并设置scrollView
垂直滚动
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!)
水平滚动
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)
第1行初始化辅助工具,传入场景尺寸。同时传入在第2步创建的可移动节点和你想要的滚动方向。
第2行设置scrollView的内容大小。
第3行添加scrollView。
第4行(水平)重置内容偏移量,以便从左到右开始(UIKit坐标与SpriteKits不同)。
- 为scrollView中的每一页添加精灵以使后续定位实际内容更容易。
垂直滚动
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)
水平滚动(定位方向相反)
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)
- 添加精灵、标签等。因为你将它们添加到上面的精灵中,所以可以像平常一样定位它们,这就是为什么先做第4步会更简单。
垂直滚动
/// 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)
水平
/// 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)
- 如果你需要禁用scrollView(例如在scrollView之上叠加另一个菜单或者按下按钮时),可以使用isDisabled布尔值。记住,UIKit元素被添加到你的GameViewController中而不是SKScenes中,所以你将不得不在此处进行调整,看看你的SpriteKit UI如何与scrollView交互。
scrollView?.isDisabled = true
- 最后,在过渡到新场景之前,不要忘记从你的场景中移除滚动视图。正如上面提到的,这是SpriteKit中处理UIKit时的一大痛点。最佳做法是在WillMoveFromView中完成。
override func willMove(from view: SKView) {
scrollView?.removeFromSuperview()
scrollView = nil // nil out reference to deallocate properly
}