在SpriteKit中模拟UIScrollView:滚动SKScene在SKView高达2000点但在高度为2050时失败时有效
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在SpriteKit中模拟UIScrollView:滚动SKScene在SKView高达2000点但在高度为2050时失败时有效相关的知识,希望对你有一定的参考价值。
目标是使用与SKScene
相同的行为滚动UIScrollView
。
其他问题类似,但答案没有帮助。
此代码说明了当SKView子视图高度为2000点时UIScrollView + SKView将如何显示内容,但如果子视图高度为2050点,则不会显示任何内容。
高度很重要,例如,如果SKScene包含3000点高的节点地图,我们需要在UIScrollView中渲染的场景(通过在SKView中呈现场景,其本身是UIScrollView的子视图)。
class TestViewController: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
// Call super
super.viewDidLoad()
// Make scene (then someone call the police)
let scene = TestScene(size: UIScreen.main.bounds.size)
// Allow other overlays to get presented
definesPresentationContext = true
// Set background color
scrollView.backgroundColor = UIColor.clear
// Create content view for scrolling since SKViews vanish with height > 2050
let contentHeight = scene.getScrollHeight()
let contentFrame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: contentHeight)
let contentView = UIView(frame: contentFrame)
contentView.backgroundColor = UIColor.clear
// Create SKView
let skFrame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: contentHeight)
let skView = SKView(frame: skFrame)
// Configure <scrollView>
scrollView.insertSubview(skView, at: 0)
scrollView.addSubview(contentView)
scrollView.delegate = self
scrollView.contentSize = contentFrame.size
// Present scene
skView.presentScene(scene)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
scene.scrollBy(offset: scrollView.contentOffset.y)
}
}
至于如何处理滚动视图,因为你只能在openGL渲染上调整大小,你需要做的是将你的场景置于滚动视图后面(不要使它成为子视图)然后将滚动坐标位置传递给场景,并相应地设置场景位置。现在,这可能会禁用场景中的触摸,因此您必须将其设置为触及其背后的视图。
这两个类演示了如何使用SKScene
行为滚动UIScrollView
菜单或场景。
感谢@KnightofDragon捕获代码中的关键缺陷。
令人沮丧的是苹果本身并不提供这种功能,但希望没有人不得不浪费时间在SpriteKit
上尝试实现菜单滚动的最佳方法!
UIViewController
假设UIScrollView
已经通过Storyboard添加。
class ScrollViewController: UIViewController, UIScrollViewDelegate {
// IB Outlets
@IBOutlet weak var scrollView: UIScrollView!
// General Vars
var scene = ScrollScene()
// =======================================================================================================
// MARK: Public Functions
// =======================================================================================================
override func viewDidLoad() {
// Call super
super.viewDidLoad()
// Create scene
scene = ScrollScene()
// Allow other overlays to get presented
definesPresentationContext = true
// Create content view for scrolling since SKViews vanish with height > ~2048
let contentHeight = scene.getScrollHeight()
let contentFrame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: contentHeight)
let contentView = UIView(frame: contentFrame)
contentView.backgroundColor = UIColor.clear
// Create SKView with same frame as <scrollView>, must manually compute because <scrollView> frame not ready at this point
let scrollViewPosY = CGFloat(0)
let scrollViewHeight = UIScreen.main.bounds.size.height - scrollViewPosY
let scrollViewFrame = CGRect(x: 0, y: scrollViewPosY, width: UIScreen.main.bounds.size.width, height: scrollViewHeight)
let skView = SKView(frame: scrollViewFrame)
view.insertSubview(skView, at: 0)
// Configure <scrollView>
scrollView.addSubview(contentView)
scrollView.delegate = self
scrollView.contentSize = contentFrame.size
// Present scene
skView.presentScene(scene)
// Handle taps on <scrollView>
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(scrollViewDidTap))
scrollView.addGestureRecognizer(tapGesture)
}
// =======================================================================================================
// MARK: UIScrollViewDelegate Functions
// =======================================================================================================
func scrollViewDidScroll(_ scrollView: UIScrollView) {
scene.scrollBy(contentOffset: scrollView.contentOffset.y)
}
// =======================================================================================================
// MARK: Gesture Functions
// =======================================================================================================
@objc func scrollViewDidTap(_ sender: UITapGestureRecognizer) {
let scrollViewPoint = sender.location(in: sender.view!)
scene.viewDidTapPoint(viewPoint: scrollViewPoint, contentOffset: scrollView.contentOffset.y)
}
}
class ScrollScene : SKScene {
// Layer Vars
let scrollLayer = SKNode()
// General Vars
var originalPosY = CGFloat(0)
// ================================================================================================
// MARK: Initializers
// ================================================================================================
override init() {
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// ================================================================================================
// MARK: Public Functions
// ================================================================================================
func scrollBy(contentOffset: CGFloat) {
scrollLayer.position.y = originalPosY + contentOffset
}
func viewDidTapPoint(viewPoint: CGPoint, contentOffset: CGFloat) {
let nodes = getNodesTouchedFromView(point: viewPoint, contentOffset: contentOffset)
}
func getScrollHeight() -> CGFloat {
return scrollLayer.calculateAccumulatedFrame().height
}
fileprivate func getNodesTouchedFromView(point: CGPoint, contentOffset: CGFloat) -> [SKNode] {
var scenePoint = convertPoint(fromView: point)
scenePoint.y += contentOffset
return scrollLayer.nodes(at: scenePoint)
}
}
以上是关于在SpriteKit中模拟UIScrollView:滚动SKScene在SKView高达2000点但在高度为2050时失败时有效的主要内容,如果未能解决你的问题,请参考以下文章
Sprite Kit中的UIScrollView水平滚动菜单