Swift SKSpriteNode:检测 Tap / DoubleTap / LongPress
Posted
技术标签:
【中文标题】Swift SKSpriteNode:检测 Tap / DoubleTap / LongPress【英文标题】:Swift SKSpriteNode: Detect Tap / DoubleTap / LongPress 【发布时间】:2014-09-28 21:01:18 【问题描述】:我正在尝试创建一个 SKSpriteNode 的子类,它可以检测用户交互(点击、双击和按住),然后遵从委托。在我看来,这似乎是一个相对普遍的需求,但是:
-
代码无法在不触发单击的情况下检测到双击。
我还没有找到检测按住/长按操作的方法。
这一切都错了吗?我不禁觉得 SpriteKit 应该有一些标准来处理如此基本的事情。我知道有 UIGestureRecognizer,但它似乎与特定的 SKNodes 而不是 UIViews 兼容。
这是我目前拥有的。根据 Apple 的示例,我在主类文件中有所有非设备特定的代码:
import SpriteKit
enum ActionType: Int
case Single
case Double
case Hold
protocol EnvironmentElementDelegate
func handleActionOnElement(element: EnvironmentElement, actionType: ActionType)
class EnvironmentElement: SKSpriteNode
let delegate: EnvironmentElementDelegate!
init(imageNamed: String, elementNamed: String, delegate: EnvironmentElementDelegate)
self.delegate = delegate
let texture = SKTexture(imageNamed: imageNamed)
super.init(texture: texture, color: UIColor.clearColor(), size: texture.size())
self.name = elementNamed
userInteractionEnabled = true
required init(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
...然后将所有 ios 特定代码放在一个单独的扩展文件中:
import SpriteKit
extension EnvironmentElement
override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
for touch: AnyObject in touches
if (touch.tapCount >= 2)
NSObject.cancelPreviousPerformRequestsWithTarget(self)
override func touchesEnded(touches: NSSet, withEvent event: UIEvent)
for touch: AnyObject in touches
if (touch.tapCount == 1)
delegate.handleActionOnElement(self, actionType: ActionType.Single)
// Unable to find Swift equivalent to this: [self performSelector:@selector(onFlip) withObject:nil afterDelay:0.3];
else
delegate.handleActionOnElement(self, actionType: ActionType.Double)
【问题讨论】:
通常当我需要一个必须检测用户点击的对象时,我使用 SKNode,它工作得更好,我在使用 SKSpriteNode 时遇到了很多问题。对于 iOS 特定代码,我将其添加到类本身,这样效果更好。 感谢 Totka 的回复,但您不会在 SKNode 中也遇到同样的问题吗?您如何检测双击和长时间保持而不是单击?我担心的是,我的代码可能与识别此类基本用户输入的最佳实践相去甚远。 我建议您使用内置的 UIGestureRecognizers,因为它们支持长按和双击(单击拒绝)。 谢谢。虽然正如我上面提到的,UIGestureRecognizers 似乎与 SpriteKit 节点不兼容:没有添加它们的函数。这就是为什么我不相信我的设计的原因。一直在阅读有关 MVC 的更多信息,也许我应该研究如何在视图级别添加识别器,然后检测从那里点击了哪个节点? 嗨。感谢您在流行的 uiscrollview 问题上添加 ios,但由于它的编辑太小,您可能很快就会面临其他审阅者的拒绝。最好还审查整个帖子以进行改进和/或在大规模编辑时等待 2000 名。 【参考方案1】:您可以在touchesBegan:
中简单地使用touch.tapCount
【讨论】:
效果很好。请注意,这不会阻止第一次触摸事件触发,例如tapCount==1 触摸在touchesBegan
和touchesEnded
上仍然触发。所以你仍然需要锻炼,可能使用定时器,延迟识别它是真正的单击还是双击。【参考方案2】:
我从来不需要检测双击,但如果我有,我会这样做:
1 - 添加一个名为 alreadyTouch
的本地变量,并在类初始化时将其设置为 false
2 - 在 touchesBegin
内部,如果 alreadyTouch
是 false
将其设置为 true
否则做你必须做的事情
3 - 设置 0.2 秒的本地 Timer
并将其添加到 if else 以检测触摸是否足够快。所以在你设置alreadyTouch = true
的地方启动这个计时器。
希望对你有帮助
【讨论】:
您好 Totka,请您提供一些示例代码行,例如您将如何运行本地 Timer? 你好,很抱歉,我失去了那个项目,或者更好的是,那个项目的高清以上是关于Swift SKSpriteNode:检测 Tap / DoubleTap / LongPress的主要内容,如果未能解决你的问题,请参考以下文章
在触摸时将动画添加到 SKSpriteNode (Swift)
skemitternode 与 skspritenode 碰撞
SKPhysicsContact未检测到categoryBitMask碰撞
如何将 SKSpriteNode 合并到 SKTexture 以在 Swift 3 中形成新的 SKSpriteNode?