将长按手势和拖动手势结合在一起
Posted
技术标签:
【中文标题】将长按手势和拖动手势结合在一起【英文标题】:Combine longpress gesture and drag gesture together 【发布时间】:2012-02-14 05:50:51 【问题描述】:我正在移动我的观点
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveRight:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[panRecognizer setDelegate:self];
[bubbleView[rightCnt] addGestureRecognizer:panRecognizer];
[panRecognizer release];
现在,我想通过长按拖动来做同样的事情。
有什么想法吗?
【问题讨论】:
【参考方案1】:UILongPressGestureRecognizer
已经为你做了你想做的事。查看UIGestureRecognizerState
属性。来自documentation:
长按手势是连续的。手势开始 (UIGestureRecognizerStateBegan) 当允许的手指数 (numberOfTouchesRequired) 已按指定时间段 (minimumPressDuration) 并且触摸不会超出 允许的移动范围(allowableMovement)。手势 每当手指移动时,识别器都会转换到 Change 状态, 并且它在任何手指时结束(UIGestureRecognizerStateEnded) 被提升了。
所以基本上在你的UILongPressGestureRecognizer
selector 被调用之后你会听 UIGestureRecognizerStateBegan、UIGestureRecognizerStateChanged、UIGestureRecognizerStateEnded。在UIGestureRecognizerStateChanged
期间不断更改您的视图框架。
- (void)moveRight:(UILongPressGestureRecognizer *)gesture
if(gesture.state == UIGestureRecognizerStateBegan)
//if needed do some initial setup or init of views here
else if(gesture.state == UIGestureRecognizerStateChanged)
//move your views here.
[yourView setFrame:];
else if(gesture.state == UIGestureRecognizerStateEnded)
//else do cleanup
【讨论】:
我正在使用 CGPoint translatePoint = [(UILongPressGestureRecognizer*)sender translationInView:self.view];但是要长按我必须使用什么? 试试[yourView setFrame:CGRectMake(xCoord,yCoord,height,width)]
但是我怎样才能得到translationPoint
为什么需要translatedPoint
?您想长按视图并拖动它吗?在UIGestureRecognizerStateEnded
中,您编写代码来获取该视图的新位置。
@SrikarAppal 你没有完全回答这个问题。 PJR 想知道每次调用UIGestureRecognizerStateChanged
时如何获取手指坐标。答案是:使用[myGestureRecognizer locationInView:aView]
【参考方案2】:
@implementation MyViewController
CGPoint _priorPoint;
- (void)moveRight:(UILongPressGestureRecognizer *)sender
UIView *view = sender.view;
CGPoint point = [sender locationInView:view.superview];
if (sender.state == UIGestureRecognizerStateChanged)
CGPoint center = view.center;
center.x += point.x - _priorPoint.x;
center.y += point.y - _priorPoint.y;
view.center = center;
_priorPoint = point;
【讨论】:
你最初将priorPoint设置为什么? 你不需要特别设置它,因为sender.state
在Changed
之前总是Began
。这意味着_priorPoint
在使用之前总是会被初始化。
但是priorPoint 最初是从(0.0, 0.0) 开始的,所以使用这个代码,初始触摸会使对象的中心移动超过点位置和中心位置的差值。我必须在Began
状态下将priorPoint 设置为视图的中心
对于未来的读者 - 我希望将 UIPanGestureRecognizer 的拖动运动与使用 UITapGestureRecognizer 对初始点击采取行动的能力相结合。我在这里玩了 UILongPressGestureRecognizer 的答案,但是虽然这似乎对其他人有用,但是在移动对象时计算对象的位置并没有达到使用 UIPanGestureRecognizer 的质量——这就是我最终返回使用的质量。对我来说,this answer 有助于提供一种同时识别手势识别器的解决方案【参考方案3】:
在 Swift 中,这可以使用下面的代码来实现
class DragView: UIView
// Starting center position
var initialCenter: CGPoint?
override func didMoveToWindow()
super.didMoveToWindow()
// Add longPress gesture recognizer
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPressAction(gesture:)))
addGestureRecognizer(longPress)
// Handle longPress action
func longPressAction(gesture: UILongPressGestureRecognizer)
if gesture.state == .began
guard let view = gesture.view else
return
initialCenter = gesture.location(in: view.superview)
else if gesture.state == .changed
guard let originalCenter = initialCenter else
return
guard let view = gesture.view else
return
let point = gesture.location(in: view.superview)
// Calculate new center position
var newCenter = view.center;
newCenter.x += point.x - originalCenter.x;
newCenter.y += point.y - originalCenter.y;
// Update view center
view.center = newCenter
else if gesture.state == .ended
...
【讨论】:
【参考方案4】:你不需要声明_priorPoint;
就我而言,我只希望视图水平移动,所以我只更改 x 坐标。
这是我的解决方案:
if (longpressGestRec.state == UIGestureRecognizerStateChanged)
UIView *view = longpressGestRec.view;
// Location of the touch within the view.
CGPoint point = [longpressGestRec locationInView:view];
// Calculate new X position based on the amount the gesture
// has moved plus the size of the view we want to move.
CGFloat newXLoc = (item.frame.origin.x + point.x) - (item.frame.size.width / 2);
[item setFrame:CGRectMake(newXLoc,
item.frame.origin.y,
item.frame.size.width,
item.frame.size.height)];
【讨论】:
您的解决方案仅适用于手指后的UIView
。想象一下,你从一张图片的一角开始UILongPress
,你想向左滑动,这张图片会跳到你手指的位置。就我而言,我必须使用_priorPoint
解决方案。【参考方案5】:
感谢 Hari Kunwar 的 Swift 代码,但 longPressAction 函数没有正确定义。
这是一个改进的版本:
@objc func longPressAction(gesture: UILongPressGestureRecognizer)
if gesture.state == UIGestureRecognizerState.began
else if gesture.state == .changed
guard let view = gesture.view else
return
let location = gesture.location(in: self.view)
view.center = CGPoint(x:view.center.x + (location.x - view.center.x),
y:view.center.y + (location.y - view.center.y))
else if gesture.state == UIGestureRecognizerState.ended
【讨论】:
以上是关于将长按手势和拖动手势结合在一起的主要内容,如果未能解决你的问题,请参考以下文章