我想将UILongPressGestureRecognizer和UIPanGestureRecognizer结合起来。
UIPanGestureRecognizer应该从长按开始。有没有简单的方法可以做到这一点?还是我真的必须编写自己的手势识别器?
我想要类似于主屏幕的效果。您按住图标一段时间后,图标会开始摇晃。之后,在屏幕上不释放手指的情况下,我可以在我的手指下开始拖动图标。
我想将UILongPressGestureRecognizer和UIPanGestureRecognizer结合起来。
UIPanGestureRecognizer应该从长按开始。有没有简单的方法可以做到这一点?还是我真的必须编写自己的手势识别器?
我想要类似于主屏幕的效果。您按住图标一段时间后,图标会开始摇晃。之后,在屏幕上不释放手指的情况下,我可以在我的手指下开始拖动图标。
实际上,您不必结合手势识别器-您可以仅使用UILongPressGestureRecognizer来完成此操作... 当您的触摸停留在'allowableMovement'中达到'minimumPressDuration'时,您进入StateBegan状态。 只要不放开任何一个手指,您就会一直停留在长按手势中-因此,您可以开始移动手指并通过StateChanged跟踪移动。
长按手势是连续的。当允许的手指数量(numberOfTouchesRequired)已经按下指定时间(minimumPressDuration),且触摸没有超出允许的移动范围(allowableMovement)时,手势开始(UIGestureRecognizerStateBegan)。当任何一个手指移动时,手势识别器转换为Change状态,并在任何一个手指抬起时结束(UIGestureRecognizerStateEnded)。
我在解决这个问题时遇到了一些困难。被采纳的答案并不足够。无论我在那个方法中放置什么,都会调用pan或longpress处理程序。我找到的解决方案如下:
UIGestureRecognizerDelegate
.Add the following delegate method to your class (as per the answer above):
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Add the following delegate method to your class:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ! shouldAllowPan) {
return NO;
}
return YES;
}
Then add either a property or ivar which will track if the pan should be allowed to begin (see method above). In my case BOOL shouldAllowPan
.
Set the BOOL to NO
in your init
or viewDidLoad
. Inside your longPress handler set the BOOL to YES
. I do it like this:
- (void) longPressHandler: (UILongPressGestureRecognizer *) gesture {
if(UIGestureRecognizerStateBegan == gesture.state) {
shouldAllowPan = NO;
}
if(UIGestureRecognizerStateChanged == gesture.state) {
shouldAllowPan = YES;
}
}
Inside the panHandler I do a check on the BOOL:
- (void)panHandler:(UIPanGestureRecognizer *)sender{
if(shouldAllowPan) {
// do your stuff
}
And finally reset the BOOL within the panHandler:
else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
shouldAllowPan = NO;
}
And then go grab a beer to congratulate yourself. ;)
Began
然后设置为 YES
即可。 if(UIGestureRecognizerStateBegan == gesture.state) {
self.shouldAllowDrag = YES;
}
而在第 6 步中,不必检查 shouldAllowPan
。——对于未格式化的代码表示抱歉。 - Dirk van Oosterbosch- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
在Swift中,Andy B的方法如下:
将UIGestureRecognizerDelegate代理添加到该类中
class ViewController: UIViewController, UIGestureRecognizerDelegate
添加一个成员变量
var shouldAllowPan: Bool = false
添加手势并需要将 pan gesture delegate 添加到 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
}
}
UIGestureRecognizerDelegate
,将UIPanGestureRecognizer
的代理设置为self,并添加gestureRecognizer(_: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith:UIGestureRecognizer)
函数,并返回true。 - RanLearns为了组合更多手势:
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)
Extension your VC and implement GestureRecognizerDelegate for implemented this method.
extension 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
}
}
我通过在“action: Selector?”函数中实现“UIPanGestureRecognizer”的所需功能来解决了这个问题,该函数是针对“UILongPressGestureRecognizer”的“action: Selector?”函数。
由于“UILongPressGestureRecognizer”没有成员“translation”,因此我通过保存原始触摸的位置并从实际触摸位置中提取它来计算翻译。
// 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)