Swift 3:UIScrollView 和(禁用)手势识别器
Posted
技术标签:
【中文标题】Swift 3:UIScrollView 和(禁用)手势识别器【英文标题】:Swift 3: UIScrollView and (disabling) Gesture Recognizers 【发布时间】:2016-11-27 20:27:48 【问题描述】:我在 swift 3 中,我有一个类是 UIScrollView 的子类。这里是:
import SpriteKit
/// Scroll direction
enum ScrollDirection
case vertical
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, scrollDirection: ScrollDirection)
self.currentScene = scene
self.moveableNode = moveableNode
self.scrollDirection = scrollDirection
super.init(frame: frame)
CustomScrollView.scrollView = self
self.frame = frame
delegate = self
indicatorStyle = .white
isScrollEnabled = true
isUserInteractionEnabled = true
//canCancelContentTouches = false
//self.minimumZoomScale = 1
//self.maximumZoomScale = 3
if scrollDirection == .horizontal
let flip = CGAffineTransform(scaleX: -1,y: -1)
transform = flip
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
/// Began
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
print("begin " + String(CustomScrollView.disabledTouches))
for touch in touches
let location = touch.location(in: currentScene)
guard !CustomScrollView.disabledTouches else return
/// Call touches began in current scene
currentScene.touchesBegan(touches, with: event)
/// Call touches began in all touched nodes in the current scene
nodesTouched = currentScene.nodes(at: location)
for node in nodesTouched
node.touchesBegan(touches, with: event)
/// Moved
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)
print("moved " + String(CustomScrollView.disabledTouches))
for touch in touches
let location = touch.location(in: currentScene)
guard !CustomScrollView.disabledTouches else return
/// Call touches moved in current scene
currentScene.touchesMoved(touches, with: event)
/// Call touches moved in all touched nodes in the current scene
nodesTouched = currentScene.nodes(at: location)
for node in nodesTouched
node.touchesMoved(touches, with: event)
/// Ended
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)
for touch in touches
let location = touch.location(in: currentScene)
guard !CustomScrollView.disabledTouches else return
/// Call touches ended in current scene
currentScene.touchesEnded(touches, with: event)
/// Call touches ended in all touched nodes in the current scene
nodesTouched = currentScene.nodes(at: location)
for node in nodesTouched
node.touchesEnded(touches, with: event)
/// Cancelled
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?)
print("cancelled " + String(CustomScrollView.disabledTouches))
for touch in touches
let location = touch.location(in: currentScene)
guard !CustomScrollView.disabledTouches else return
/// Call touches cancelled in current scene
currentScene.touchesCancelled(touches, with: event)
/// Call touches cancelled in all touched nodes in the current scene
nodesTouched = currentScene.nodes(at: location)
for node in nodesTouched
node.touchesCancelled(touches, with: event)
// MARK: - Touch Controls
extension CustomScrollView
/// Disable
class func disable()
CustomScrollView.scrollView?.isUserInteractionEnabled = false
CustomScrollView.disabledTouches = true
/// Enable
class func enable()
CustomScrollView.scrollView?.isUserInteractionEnabled = 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
它的主要功能是创建一个可滚动的菜单,并且大部分情况下它都可以工作。我在 GameScene 中创建了它的一个对象,它的工作原理是当注册触摸时,会调用 CustomScrollView 中覆盖的触摸函数(touchBegan、touchMoved 等),然后调用 GameScene 中的触摸函数。这确实发生了,菜单滚动正常,并且调用了 GameScene 的方法。
关键是我的覆盖函数(和 GameScene 的)只有在您水平滑动时才会被调用。当您向上或向下滑动(超过一定程度)时,菜单仍会滚动,但我认为正在调用的是 UIScrollView 的触摸方法。
当你垂直滑动时,我的 touchCancelled 方法被调用,这让我认为这与 UIScrollView 的手势识别器(我认为是平移/拖动识别器)在不应该触发时触发有关。
是这样吗?如果是这样,我可以禁用识别器吗?如果可以,我应该吗?附带说明一下,这是实现 UIScrollView 以便仍然调用 GameScene 的触摸方法的最佳(或至少是可接受的)方法吗?
【问题讨论】:
【参考方案1】:如果需要同时识别冲突的手势识别器,可以使用gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:),
【讨论】:
以上是关于Swift 3:UIScrollView 和(禁用)手势识别器的主要内容,如果未能解决你的问题,请参考以下文章
Swift 3 - UITableView 在 UIScrollView 中被切断
Swift 3 - 如何在 .xib 文件上为 UIScrollView 分配委托?