Combine longpress gesture and drag gesture together
Solution 1
UILongPressGestureRecognizer
already does what you want for you. Take a look at the UIGestureRecognizerState
property. From the documentation:
Long-press gestures are continuous. The gesture begins (UIGestureRecognizerStateBegan) when the number of allowable fingers (numberOfTouchesRequired) have been pressed for the specified period (minimumPressDuration) and the touches do not move beyond the allowable range of movement (allowableMovement). The gesture recognizer transitions to the Change state whenever a finger moves, and it ends (UIGestureRecognizerStateEnded) when any of the fingers are lifted.
So essentially after your UILongPressGestureRecognizer
selector is called you listen to UIGestureRecognizerStateBegan, UIGestureRecognizerStateChanged, UIGestureRecognizerStateEnded. Keep changing your views frame during 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
}
}
Solution 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;
}
Solution 3
In Swift this can be achieved using below code
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 {
...
}
}
Solution 4
You do not need to declare _priorPoint;
In my case, i only want the view to move horizontally so i'm only changing the x coordinate.
Here is my solution:
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)];
}
Solution 5
Thanks to Hari Kunwar for the Swift code, but the longPressAction function is not correctly defined.
Here's an improved version:
@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{
}
}
PJR
Check my Sample codes on Github: https://github.com/paritsohraval100 Cocoa Controls https://www.cocoacontrols.com/controls/pjr-scrollview-slider https://www.cocoacontrols.com/controls/pjr-nsstring-category https://www.cocoacontrols.com/controls/pjrsignaturedemo https://www.cocoacontrols.com/controls/pulseanimation Please check My Blog: http://iosdevblogs.blogspot.in/
Updated on July 09, 2022Comments
-
PJR almost 2 years
I'm moving my views by
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveRight:)]; [panRecognizer setMinimumNumberOfTouches:1]; [panRecognizer setMaximumNumberOfTouches:1]; [panRecognizer setDelegate:self]; [bubbleView[rightCnt] addGestureRecognizer:panRecognizer]; [panRecognizer release];
Now , I want to do same thing by drag with long press.
Any idea?
-
PJR about 12 yearsi am using CGPoint translatedPoint = [(UILongPressGestureRecognizer*)sender translationInView:self.view]; but tor long press what i have to use ?
-
Srikar Appalaraju about 12 yearstry
[yourView setFrame:CGRectMake(xCoord,yCoord,height,width)]
-
PJR about 12 yearsbut by this how can i get translatedPoint
-
Srikar Appalaraju about 12 yearswhy do you need
translatedPoint
? You want to longtap on a view & drag it around right? inUIGestureRecognizerStateEnded
you write code to get the new location for that view. -
Fabio over 9 yearsyour solution only works for a
UIView
following the finger. Imagine you start theUILongPress
from the corner of a picture and you want to swipe left, this picture would jump to the position of your finger. In my case, I had to use a_priorPoint
solution. -
Martin almost 8 years@SrikarAppal you do not answer totally to the question. PJR wanted to know how to get the finger coordinates each time
UIGestureRecognizerStateChanged
was called. And the answer was: by using[myGestureRecognizer locationInView:aView]
-
Munib over 7 yearsThanks so much, I would like to point out that this is the best solution for checking a long press gesture and a drag into a certain UIView. Saves the hassle of figuring out touchesmoved etc.. Thanks!
-
RanLearns about 6 yearswhat do you set priorPoint to initially?
-
rob mayoff about 6 yearsYou don't need to set it to anything in particular, because
sender.state
will always beBegan
before it isChanged
. This means_priorPoint
will always be initialized before it is used. -
RanLearns about 6 yearsBut priorPoint starts off initially as (0.0, 0.0) so with this code the initial touch would move the center of the object by more than the difference of the point's location and the center's location. I had to set priorPoint to the view's center in the
Began
state -
RanLearns about 6 yearsFor future readers - I was hoping to combine the dragging movement of UIPanGestureRecognizer with the ability to take action on the initial tap using UITapGestureRecognizer. I played around with the answers here for UILongPressGestureRecognizer but while this seems to have worked for others, the calculation of the object's position as it is moved didn't reach the quality of using UIPanGestureRecognizer - which is what I ended up returning to using. For me this answer was helpful in providing a solution to recognize simultaneous gesture recognizers