10

I want to tap on a UIView and drag and have that view follow my finger, simple enough. But the easiest way of doing this is by setting the objects center to where the tap happened (Which is not what I want), I want it to move as if you grabbed the object wherever you tapped it.

There was a very useful way of doing this and it was reference in one of the iTunes U videos. The script didn't use deltaX, deltaY for dragging the image underneath where you tapped on it instead of having it center underneath your finger but I can't remember what that code was!

Does anyone have a reference to this code? Or perhaps have an efficient way of moving UIViews under a finger without having the uiview.center = tap.center concept?

Parad0x13
  • 2,007
  • 3
  • 23
  • 38

4 Answers4

14

The following code is an example of a simple gesture recognizer that will allow panel / view movement. Instead of modifying the center, you're modifying the origin point [basically by setting a new frame for the target view].

You can optimize this in your situation so you're not having to drill down into the gesture.view... etc

-(void)dragging:(UIPanGestureRecognizer *)gesture
{
    if(gesture.state == UIGestureRecognizerStateBegan)
    {
        //NSLog(@"Received a pan gesture");
        self.panCoord = [gesture locationInView:gesture.view];


    }
    CGPoint newCoord = [gesture locationInView:gesture.view];
    float dX = newCoord.x-panCoord.x;
    float dY = newCoord.y-panCoord.y;

gesture.view.frame = CGRectMake(gesture.view.frame.origin.x+dX, gesture.view.frame.origin.y+dY, gesture.view.frame.size.width, gesture.view.frame.size.height);
 }

Swift 4:

@objc func handleTap(_ sender: UIPanGestureRecognizer) {
        if(sender.state == .began) {
            self.panCoord = sender.location(in: sender.view)
        }

        let newCoord: CGPoint = sender.location(in: sender.view)

        let dX = newCoord.x - panCoord.x
        let dY = newCoord.y - panCoord.y

        sender.view?.frame = CGRect(x: (sender.view?.frame.origin.x)!+dX, y: (sender.view?.frame.origin.y)!+dY, width: (sender.view?.frame.size.width)!, height: (sender.view?.frame.size.height)!)
    }
Hapeki
  • 2,153
  • 1
  • 20
  • 36
binary_falcon
  • 302
  • 3
  • 11
  • 2
    what is "panCoord" in your code? – George Asda Jul 22 '12 at 11:15
  • My apologies, panCoord is the local CGPoint that keeps track of where it is currently being panned to. I didn't realize the dependency was there and unresolved. Please add a CGPoint panCoord to store the current location of "where to move from" – binary_falcon Oct 31 '12 at 15:30
7

Here is the code from Apple's MoveMe project the key is to do this in the touchesMoved method. It allows the UIView(PlacardView) to see the touch and move wherever the user's touch goes. Hope this helps.

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

UITouch *touch = [touches anyObject];

// If the touch was in the placardView, move the placardView to its location
if ([touch view] == placardView) {
    CGPoint location = [touch locationInView:self];
    placardView.center = location;
    return;
   }
}
Mykola
  • 3,343
  • 6
  • 23
  • 39
tony.stack
  • 780
  • 8
  • 21
  • 4
    Problem with this is if you move your finger event without starting in the view, it will change its position, and this causes a jump. – Nuno Gonçalves Apr 17 '15 at 16:48
  • It is already pointing into the right direction! But that's what I thought too when I read it :) – Alex Cio Jul 15 '16 at 19:23
0

I think you are talking about the stalker app...

// Tell the "stalker" rectangle to move to each touch-down
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [UIView beginAnimations:@"stalk" context:nil];
    [UIView setAnimationDuration:1];
    //[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationBeginsFromCurrentState:YES];

    // touches is an NSSet.  Take any single UITouch from the set
    UITouch *touch = [touches anyObject];

    // Move the rectangle to the location of the touch
    stalker.center = [touch locationInView:self];
    [UIView commitAnimations];
}
TigerCoding
  • 8,710
  • 10
  • 47
  • 72
  • 1
    Thanks for the code, but this isn't what I'm trying to accomplish. I want the object to move under my finger as I drag so that the center of the UIView is displaced according to how I move my finger instead of centering on my finger – Parad0x13 Feb 12 '11 at 23:37
  • 1
    @Parad0x13 Hey have you got any solution for your prob? then let me know please as i am facing same situation and I need to solve it. – Zalak Patel Feb 24 '15 at 04:51
0

You can save both the point where you touched (T) and the current position of the view (O). In touchMoved, you can move it based on the new point by adding (O-T).

Eduardo Costa
  • 1,974
  • 1
  • 16
  • 22
  • Right, I could do this. But there is another cleaner way to do it. There is a framework native to UIView that can accomplish what I want without having to do the math myself – Parad0x13 Feb 12 '11 at 23:38
  • 1
    I beg you pardon. Are you asking or making an affirmation? :) If you found such framework, add a comment here (or answer your own question), to make the knowledge public! ;) – Eduardo Costa Feb 14 '11 at 21:37