touchesBegan, touchesEnded, touchesMoved for moving UIView
Asked Answered
D

4

20

I need to drag my UIView object. I use this code, but it does not work

float oldX, oldY;
BOOL dragging;

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

    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:self];

    if ([[touch.view class] isSubclassOfClass:[UILabel class]]) {
        UILabel *label = (UILabel *)touch.view;
        if (CGRectContainsPoint(label.frame, touchLocation)) {
            dragging = YES;
            oldX = touchLocation.x;
            oldY = touchLocation.y;
        }
    }


}

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

    dragging = NO;
}

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

    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:self];

    if ([[touch.view class] isSubclassOfClass:[UILabel class]]) {
        UILabel *label = (UILabel *)touch.view;

        if (dragging) {
            CGRect frame = label.frame;
            frame.origin.x = label.frame.origin.x + touchLocation.x - oldX;
            frame.origin.y =  label.frame.origin.y + touchLocation.y - oldY;
            label.frame = frame;
        }

    }


}
Desilva answered 13/2, 2013 at 15:24 Comment(3)
check out this answer this SO answer https://mcmap.net/q/495352/-uiview-drag-image-and-textFelony
What does actually happen?Nagari
the problem is connected to moving object. when i tap on object it has to remember coords and then when we recalculate its frame in method -touchesMoved it should move but it does not. it moves just in one directionDesilva
P
0

There's something a bit strange in your code.

You ask for the location in self, some UIView which presumably contains the UILabel you want to check. This begs the question as to why you do not add the touchesXXX to some UILabel subclass of yours.

This cancels out as you're using the label.frame which is defined in terms of its superview.bounds (your parent UIView you asked the touch location with respect to), but this doesn't make for the most straightforward way to follow what's going on.

Philina answered 13/2, 2013 at 16:15 Comment(1)
yes, you are right I have changed self to touch.view and remove if block for checking point in rect. thanksDesilva
N
16

I would suggest using a UIPanGestureRecognizer:

-(void)dragging:(UIPanGestureRecognizer *)gesture
{
    // Check if this is the first touch
    if(gesture.state == UIGestureRecognizerStateBegan)
    {
        // Store the initial touch so when we change positions we do not snap
        self.panCoord = [gesture locationInView:gesture.view];
        [self.view bringSubviewToFront:gesture.view];

    }

    CGPoint newCoord = [gesture locationInView:gesture.view];

    // Create the frame offsets to use our finger position in the view.
    float dX = newCoord.x-self.panCoord.x;
    float dY = newCoord.y-self.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);
}

This is just a preference of mine. To me it is a lot simpler using a gesture recognizer then using touchesBegan, touchesEnded, touchesMoved. I will use these in cases where the UIPanGestureRecognizer will not work.

Numen answered 13/2, 2013 at 16:5 Comment(4)
it is ok, thanks, but the gesture recognizer does not have touchDown method that invokes for example in touchesBegan, just StateBegan. but StateBegan works in the one way when we move object instead when we tap on itDesilva
Yes it does you can use UIGestureRecognizerStateBegan, UIGestureRecognizerStateChanged,UIGestureRecognizerStateEnded,UIGestueRecognizerStateCancelled,UIGestureRecognizerStateFailed. UIGestureRecognizerStateBegan will give you your initial touch(on pan). If you want a different action for tap add the UITapGestureNumen
Hi what kind of variable is self.panCoord?Dichogamy
Hi, just wondering how would I move a label or something in a view with this? Is "self.panCoord" a CGPoint?Dichogamy
D
14

This is work code for move UIView objects

float oldX, oldY; BOOL dragging;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:touch.view];
    if ([[touch.view class] isSubclassOfClass:[UILabel class]]) {
        dragging = YES;
        oldX = touchLocation.x;
        oldY = touchLocation.y;
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    dragging = NO;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:touch.view];    
    if ([[touch.view class] isSubclassOfClass:[UILabel class]]) {
        UILabel *label = (UILabel *)touch.view;
        if (dragging) {
            CGRect frame = label.frame;
            frame.origin.x = label.frame.origin.x + touchLocation.x - oldX;
            frame.origin.y = label.frame.origin.y + touchLocation.y - oldY;
            label.frame = frame;
        }
    }
}
Desilva answered 13/2, 2013 at 16:25 Comment(0)
P
0

There's something a bit strange in your code.

You ask for the location in self, some UIView which presumably contains the UILabel you want to check. This begs the question as to why you do not add the touchesXXX to some UILabel subclass of yours.

This cancels out as you're using the label.frame which is defined in terms of its superview.bounds (your parent UIView you asked the touch location with respect to), but this doesn't make for the most straightforward way to follow what's going on.

Philina answered 13/2, 2013 at 16:15 Comment(1)
yes, you are right I have changed self to touch.view and remove if block for checking point in rect. thanksDesilva
D
0

With this code i could move my UIView Object anywhere. My ViewController.swift looks like this.

// code from below

import UIKit

class ViewController: UIViewController {

    var location = CGPoint(x: 0, y: 0)

    @IBOutlet weak var Person: UIImageView!

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        var touch : UITouch! =  touches.first! as UITouch

        location = touch.location(in: self.view)

        Person.center = location

    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

        var touch : UITouch! =  touches.first! as UITouch

        location = touch.location(in: self.view)

        Person.center = location
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        Person.center = CGPoint(x: 160, y: 330)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

//ends

Hope it helps although it is another way to do it than the one mentioned in question.

Delegation answered 29/12, 2016 at 11:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.