我想将 UILongPressGestureRecognizer 与 UIPanGestureRecognizer 结合使用。
UIPanGestureRecognizer 应该以长按开始。有没有一种简单的方法可以做到这一点?还是我真的必须编写自己的手势识别器?
我不想在主屏幕上显示类似的东西。您按下一个图标,一段时间后图标开始摆动。之后,无需从屏幕上松开手指,我就可以开始拖动手指下的图标。
我想将 UILongPressGestureRecognizer 与 UIPanGestureRecognizer 结合使用。
UIPanGestureRecognizer 应该以长按开始。有没有一种简单的方法可以做到这一点?还是我真的必须编写自己的手势识别器?
我不想在主屏幕上显示类似的东西。您按下一个图标,一段时间后图标开始摆动。之后,无需从屏幕上松开手指,我就可以开始拖动手指下的图标。
实际上,您不必组合手势识别器 - 您可以仅使用 UILongPressGestureRecognizer 完成此操作......一旦您的触摸保持在“minimumPressDuration”的“allowableMovement”范围内,您就进入了 StateBegan。只要您不抬起任何手指,您就可以保持连续的 longPressGesture - 因此您可以开始移动手指并通过 StateChanged 跟踪移动。
长按手势是连续的。当允许的手指数量 (numberOfTouchesRequired) 在指定的时间 (minimumPressDuration) 内被按下并且触摸没有超出允许的移动范围 (allowableMovement) 时,手势开始 (UIGestureRecognizerStateBegan)。每当手指移动时,手势识别器就会转换到 Change 状态,并在任何手指抬起时结束 (UIGestureRecognizerStateEnded)。
这个问题我有点难。接受的答案还不够。无论我在该方法中放入什么,都会调用 pan 或 longpress 处理程序。我找到的解决方案如下:
UIGestureRecognizerDelegate
.将以下委托方法添加到您的类(根据上面的答案):
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
将以下委托方法添加到您的类:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ! shouldAllowPan) {
return NO;
}
return YES;
}
然后添加一个属性或 ivar,它将跟踪是否应该允许开始平移(参见上面的方法)。就我而言BOOL shouldAllowPan
。
将 BOOL 设置为NO
在您的init
orviewDidLoad
中。在您的 longPress 处理程序中,将 BOOL 设置为YES
. 我这样做:
- (void) longPressHandler: (UILongPressGestureRecognizer *) gesture {
if(UIGestureRecognizerStateBegan == gesture.state) {
shouldAllowPan = NO;
}
if(UIGestureRecognizerStateChanged == gesture.state) {
shouldAllowPan = YES;
}
}
在 panHandler 内部,我检查了 BOOL:
- (void)panHandler:(UIPanGestureRecognizer *)sender{
if(shouldAllowPan) {
// do your stuff
}
最后在 panHandler 中重置 BOOL:
else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
shouldAllowPan = NO;
}
然后去喝啤酒祝贺自己。;)
我找到了一个解决方案:这个 UIGestureRecognizerDelegate 方法完全符合我的要求:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
Andy B 在 Swift 中的方法,
将UIGestureRecognizerDelegate委托添加到类
class ViewController: UIViewController, UIGestureRecognizerDelegate
添加成员变量
var shouldAllowPan: Bool = false
添加手势,需要将平移手势委托添加到VC。这是触发 shouldRecognizeSimultaneouslyWithGestureRecognizer 和 gestureRecognizerShouldBegin 函数所必需的
// long press
let longPressRec = UILongPressGestureRecognizer(target: self, action: "longPress:")
yourView.addGestureRecognizer(longPressRec)
// drag
let panRec = UIPanGestureRecognizer(target: self, action: "draggedView:")
panRec.delegate = self
yourView.addGestureRecognizer(panRec)
允许同时使用手势
func gestureRecognizer(UIGestureRecognizer,
shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
// println("shouldRecognizeSimultaneouslyWithGestureRecognizer");
return true
}
func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
// We only allow the (drag) gesture to continue if it is within a long press
if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) {
return false;
}
return true;
}
在长按处理程序内部:
func longPress(sender: UILongPressGestureRecognizer) {
if(sender.state == .Began) {
// handle the long press
}
else if(sender.state == .Changed){
shouldAllowPan = true
}
else if (sender.state == .Ended) {
shouldAllowPan = false
}
}
组合更多手势:
var shouldAllowSecondGesture : Bool = false
let longPressRec = UILongPressGestureRecognizer(target: self, action: #selector(self.startDrag(sender:)))
cell.addGestureRecognizer(longPressRec)
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(sender:)))
cell.isUserInteractionEnabled = true
cell.addGestureRecognizer(panGestureRecognizer)
扩展您的 VC 并实现 GestureRecognizerDelegate 以实现此方法。
扩展 YourViewController : UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
// We only allow the (drag) gesture to continue if it is within a long press
if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) {
return false
}
return true
}
@objc func startDrag(sender:UIPanGestureRecognizer) {
if(sender.state == .began) {
// handle the long press
}
else if(sender.state == .changed){
shouldAllowPan = true
}
else if (sender.state == .ended) {
shouldAllowPan = false
}
}
阅读 Apple 的 UIGestureRecognizer 类参考的“子类化注释”部分:
我通过实现“动作:选择器?”的所需功能解决了这个问题。“动作:选择器?”中 UIPanGestureRecognizer 的函数 UILongPressGestureRecognizer 的函数。
由于“UILongPressGestureRecognizer”没有成员“翻译”,我通过保存原始触摸的位置并将其从实际触摸位置中提取来计算翻译。
// in target class
var initialTouchX : CGFloat
var initialTouchX : CGFloat
// in the @objc func for the UILongPressGestureRecognizer
if sender.state == .began {
initialTouchX = sender.location(in: sender.view).x
initialTouchY = sender.location(in: sender.view).y
}
let translation = CGVector(dx: sender.location(in: sender.view).x - initialTouchX, dy: sender.location(in: sender.view).y - initialTouchY)