【问题标题】:How to move a UIImageView with Touch如何使用 Touch 移动 UIImageView
【发布时间】:2012-02-25 18:19:27
【问题描述】:

我正在尝试为我的 imageView(下面代码中的 maskPreview)创建移动功能,以便用户可以在屏幕周围移动包含在 maskPreview 中的图片。这是我的触摸开始和触摸移动的代码:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count]==1) {
    UITouch *touch= [touches anyObject];
    originalOrigin = [touch locationInView:maskPreview];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count]==1) {
    UITouch *touch = [touches anyObject];
    CGPoint lastTouch = [touch previousLocationInView:self.view];
    CGFloat movedDistanceX = originalOrigin.x-lastTouch.x;
    CGFloat movedDistanceY = originalOrigin.y-lastTouch.y;
    [maskPreview setFrame:CGRectMake(maskPreview.frame.origin.x+movedDistanceX, maskPreview.frame.origin.y + movedDistanceY, maskPreview.frame.size.width, maskPreview.frame.size.height)];
}
}

但我从应用程序中收到了一些奇怪的响应。我没有限制 imageview 可以移动多远,即防止它离开屏幕,但即使是一个小动作,我的 imageview 也会变得疯狂并消失。

在此先感谢大家的帮助

【问题讨论】:

    标签: cocoa-touch uiimageview user-interaction


    【解决方案1】:

    在这个现代世界中,实现touchesBegan 等等实在是太过分了。你只是把自己搞糊涂了,你的代码很快就会变得无法理解或维护。使用 UIPanGestureRecognizer;这就是它的用途。使用 UIPanGestureRecognizer 使视图可拖动是微不足道的。这是使视图可拖动的 UIPanGestureRecognizer 的操作处理程序:

    - (void) dragging: (UIPanGestureRecognizer*) p {
        UIView* vv = p.view;
        if (p.state == UIGestureRecognizerStateBegan ||
            p.state == UIGestureRecognizerStateChanged) {
            CGPoint delta = [p translationInView: vv.superview];
            CGPoint c = vv.center;
            c.x += delta.x; c.y += delta.y;
            vv.center = c;
            [p setTranslation: CGPointZero inView: vv.superview];
        }
    }
    

    【讨论】:

    • 真棒马特,你是一个绝对的天才!会评价你的答案,但我没有足够的声誉!让我的生活变得轻松多了!
    • 仅供参考,该代码直接来自我的书中:shop.oreilly.com/product/0636920023562.do - 更多来自哪里...
    【解决方案2】:

    您的代码有两个问题。首先,这一行是错误的:

    CGPoint lastTouch = [touch previousLocationInView:self.view];
    

    应该是这样的:

    CGPoint lastTouch = [touch previousLocationInView:maskPreview];
    

    真的,你甚至不应该使用previousLocationInView:。你应该像这样使用locationInView:

    CGPoint lastTouch = [touch locationInView:maskPreview];
    

    其次,你得到了movedDistanceXmovedDistanceY 的符号错误。将它们更改为:

    CGFloat movedDistanceX = lastTouch.x - originalOrigin.x;
    CGFloat movedDistanceY = lastTouch.y - originalOrigin.y;
    

    另外,touchesBegan:withEvent: 的文档是这样说的:

    如果您在不调用super 的情况下覆盖此方法(一种常见的使用模式),那么您还必须覆盖用于处理触摸事件的其他方法,如果只是作为存根(空)实现。

    因此,请确保您还覆盖了 touchesEnded:withEvent:touchesCancelled:withEvent:

    无论如何,您可以更简单地执行此操作。一种方法是使touchesBegan:withEvent: 为空并使用previousLocationInView:locationInView: 完成touchesMoved:withEvent: 中的所有工作,并更新maskPreview.center 而不是maskPreview.frame。你甚至不需要originalOrigin 实例变量:

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
    }
    
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    {
        if ([touches count]==1) {
            UITouch *touch = [touches anyObject];
            CGPoint p0 = [touch previousLocationInView:maskPreview];
            CGPoint p1 = [touch locationInView:maskPreview];
            CGPoint center = maskPreview.center;
            center.x += p1.x - p0.x;
            center.y += p1.y - p0.y;
            maskPreview.center = center;
        }
    }
    

    另一种方法是使用UIPanGestureRecognizer。我把它留给读者作为练习。

    【讨论】:

    • 嗨 Rob,感谢您的回答,并意识到我的代码中的错误!我使用了 Matt 的 UIPanGestureRecognizer 教程,效果很好。但是关于覆盖所有触摸事件的一点帮助很大,我不知道也不认为我们应该这样做。
    猜你喜欢
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 2011-03-12
    相关资源
    最近更新 更多