使用 SwiftUI 时无法正确调整 SKScene 的大小
Posted
技术标签:
【中文标题】使用 SwiftUI 时无法正确调整 SKScene 的大小【英文标题】:Unable to properly size SKScene when working with SwiftUI 【发布时间】:2019-10-07 14:17:42 【问题描述】:我正在尝试将SpriteKit
与基于SwiftUI
的接口一起使用,但在初始化我的SKScene
时遇到了问题。
首先,包含SKView
的UIViewRepresentable
取自similar question:
struct SpriteKitContainer: UIViewRepresentable
let scene: SKScene
func makeUIView(context: Context) -> SKView
return SKView(frame: .zero)
func updateUIView(_ view: SKView, context: Context)
view.presentScene(scene)
这里的一个关键部分是它需要在初始化 SpriteKitContainer
之前初始化 SKScene
。
我目前有以下缩写的 sn-p 这样做:
import SwiftUI
import SpriteKit
struct GameView: View
@State private var isEnabled = true
var body: some View
let tapGesture = TapGesture()
.onEnded value in
// This size is obviously wrong
let size = UIScreen.main.bounds.size
let scene = Scene(size: size)
scene.scaleMode = .resizeFill
return SpriteKitContainer(scene: scene)
.disabled(!isEnabled)
.frame(maxWidth: .infinity,
maxHeight: .infinity,
alignment: .center)
.gesture(tapGesture)
.padding(.all, 30)
我只包含TapGesture
来说明为什么body
的结构是这样的。包含代码后,一切都会按预期工作,但场景使用的大小显然是错误的(它无法考虑填充和导航元素)。
但是,我目前还没有找到任何其他方法来获取大小或框架,并且为 Scene(size:)
调用发送 .zero
大小也不会正确调整大小。
我的假设是,由于我仍在使用 SwiftUI,因此我错过了一些前导步骤。否则,我可以根据我所知道的计算出一个新的CGSize
,但这让我觉得这里的方法是错误的。
【问题讨论】:
你的场景总是会根据视图调整大小,如果你需要填充,你需要在视图级别考虑它 【参考方案1】:在 SwiftUI 中,您需要使用 GeometryReader 作为代理来获取视图的当前大小(每次重建视图时都会发生这种情况)。然后,您希望根据父级的大小调整 UIViewRepresentable 的大小只有在大小实际发生变化时。我在这里有一个 GeometryReader 示例:https://github.com/joshuajhomann/SwiftUI-Spirograph
【讨论】:
谢谢,我终于能够回到这个问题上,你把我带到了正确的区域并结合***.com/questions/56729619/…,我能够让它工作。【参考方案2】:SKScene
有一个 didChangeSize
方法用于这样的场景:
override func didChangeSize(_ oldSize: CGSize)
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
来自Apples Documentation:
此方法旨在在子类中被覆盖。通常,您 使用此方法调整场景中节点的位置。
【讨论】:
【参考方案3】:您不需要 GeometryReader。只需让 SwiftUI 本身为您的 SpriteView 提供可用空间。重要的是,视图大小不是自动场景大小。因此,您必须明确设置场景大小。
import SwiftUI
import SpriteKit
struct ContentView: View
var body: some View
SpriteView(scene: spriteKitScene)
private var spriteKitScene : SKScene
let scene = SpriteKit_View()
scene.scaleMode = .aspectFit
return scene
class SpriteKit_View : SKScene
override func didMove(to view: SKView)
// Set the scene size as you want, in my case
equal to the views size
size = view.frame.size
// ...
场景大小可以与视图大小完全不同,这就是场景 scaleMode 发挥作用的时候。
【讨论】:
以上是关于使用 SwiftUI 时无法正确调整 SKScene 的大小的主要内容,如果未能解决你的问题,请参考以下文章
调整窗口大小时,SwiftUI TextField 文本边界无法使用 GeometryReader 更新,导致外观错误
带有 SpriteView 和 SwiftUI 的场景不会填满整个屏幕
在 SwiftUI 中添加 Rectangle() 时单元格行自动调整大小损坏