touchesBegan、touchesEnded和touchesMoved用于移动UIView。

20

我需要拖动我的UIView对象。我使用了这段代码,但它不起作用。

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;
        }

    }


}

请查看此stackoverflow答案:https://dev59.com/uW445IYBdhLWcg3wNXg_#4983124 - luksfarris
实际上发生了什么? - trojanfoe
问题与移动对象有关。当我点击对象时,它必须记住坐标,然后在方法-touchesMoved中重新计算其框架时应该移动,但它没有移动。它只朝一个方向移动。 - Matrosov Oleksandr
4个回答

16

我建议使用一个 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);
}

这只是我的偏好。对我来说,使用手势识别器比使用 touchesBegantouchesEndedtouchesMoved 要简单得多。在无法使用 UIPanGestureRecognizer 的情况下,我会使用这些。


没问题,谢谢。但是手势识别器没有touchDown方法,例如在touchesBegan中调用,只有StateBegan。但是StateBegan仅适用于移动对象,而不适用于点击对象。 - Matrosov Oleksandr
是的,你可以使用UIGestureRecognizerStateBegan、UIGestureRecognizerStateChanged、UIGestureRecognizerStateEnded、UIGestueRecognizerStateCancelled、UIGestureRecognizerStateFailed。UIGestureRecognizerStateBegan将给出您的初始触摸(在平移时)。如果您想要不同的点击操作,请添加UITapGesture。 - Jaybit
你好,self.panCoord是什么类型的变量? - uplearned.com
嗨,我想知道如何在视图中移动标签或其他元素?“self.panCoord”是一个CGPoint吗? - uplearned.com

14

这是移动UIView对象的工作代码

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;
        }
    }
}

0

你的代码有些奇怪。

你在 self 中寻找位置,它是一个 UIView,里面很可能包含了你想要检查的 UILabel。这引出了一个问题,为什么你不把 touchesXXX 添加到你自己的 UILabel 子类中呢?

虽然这可以取消掉,因为你正在使用 label.frame 来定义其 superview.bounds(即你要求触摸位置的父 UIView),但这并不是最直接的方式来理解正在发生的事情。


是的,你说得对。我已经将self更改为touch.view,并删除了用于检查点是否在矩形内的if块。谢谢。 - Matrosov Oleksandr

0

使用这段代码,我可以将我的UIView对象移动到任何位置。 我的ViewController.swift文件如下。

// 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

希望这能有所帮助,虽然这是一种与问题中提到的方法不同的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接