如何继续drawRect:当手指在屏幕上

时间:2014-04-03 01:35:02

标签: ios drawrect uitouch

我有当前的代码:

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

    self.objectPoint = [[touches anyObject] locationInView:self];
    float x, y;
    if (self.objectPoint.x > self.objectPoint.x) {
        x = self.objectPoint.x + 1;
    }
    else x = self.objectPoint.x - 1;
    if (self.fingerPoint.y > self.objectPoint.y) {
        y = self.objectPoint.y + 1;
    }
    else y = self.minionPoint.y - 1;
    self.objectPoint = CGPointMake(x, y);

    [self setNeedsDisplay];
}

我的问题是我想让对象跟在你的手指上,直到你的手指离开屏幕。只有在我的手指移动时它才会跟随。 touchesEnded仅在我将手指从屏幕上移开时才起作用,因此这也不是我想要的。我怎样才能启用可以解决问题的东西?

2 个答案:

答案 0 :(得分:1)

如果您想要触摸屏幕的一部分,并且只要您按住手指就想要在该方向上移动绘制的对象,则有几种方法。

接近是使用某种形式的计时器,当用户将手指放在屏幕上时,会反复调用方法(因为,正如您所指出的,您只会在touchesMoved时获得更新你挪开)。虽然NSTimer是您遇到的最常见的计时器,但在这种情况下,您需要使用称为显示链接的专用计时器CADisplayLink,当可以执行屏幕更新时会触发。所以,你会:

  • touchesBegan中,捕获用户在屏幕上触摸的位置并启动CADisplayLink;

  • touchesMoved中,您需要更新用户的触摸位置(但只有在他们移动手指时才会调用);

  • touchesEnded中,您可能会停止显示链接;和

  • CADisplayLink处理程序中,您需要更新位置(并且您需要知道您希望它移动的速度)。

所以,这看起来像是:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.velocity = 100.0;     // 100 points per second
    self.touchLocation = [[touches anyObject] locationInView:self];

    [self startDisplayLink];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.touchLocation = [[touches anyObject] locationInView:self];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self stopDisplayLink];
}

- (void)startDisplayLink
{
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    self.lastTimestamp = CACurrentMediaTime();   // initialize the `lastTimestamp`
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopDisplayLink
{
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
    // figure out the time elapsed, and reset the `lastTimestamp`

    CFTimeInterval currentTimestamp = CACurrentMediaTime();
    CFTimeInterval elapsed = currentTimestamp - self.lastTimestamp;
    self.lastTimestamp = currentTimestamp;

    // figure out distance to touch and distance we'd move on basis of velocity and elapsed time

    CGFloat distanceToTouch  = hypotf(self.touchLocation.y - self.objectPoint.y, self.touchLocation.x - self.objectPoint.x);
    CGFloat distanceWillMove = self.velocity * elapsed;

    // this does the calculation of the angle between the touch location and
    // the current `self.objectPoint`, and then updates `self.objectPoint` on
    // the basis of (a) the angle; and (b) the desired velocity.

    if (distanceToTouch == 0.0)                  // if we're already at touchLocation, then just quit
        return;
    if (distanceToTouch < distanceWillMove) {    // if the distance to move is less than the target, just move to touchLocation
        self.objectPoint = self.touchLocation;
    } else {                                     // otherwise, calculate where we're going to move to
        CGFloat angle = atan2f(self.touchLocation.y - self.objectPoint.y, self.touchLocation.x - self.objectPoint.x);
        self.objectPoint = CGPointMake(self.objectPoint.x + cosf(angle) * distanceWillMove,
                                       self.objectPoint.y + sinf(angle) * distanceWillMove);
    }
    [self setNeedsDisplay];
}

要使用它,您需要定义一些属性:

@property (nonatomic) CGFloat velocity;
@property (nonatomic) CGPoint touchLocation;
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic) CFTimeInterval lastTimestamp;

答案 1 :(得分:0)

如果您想用手指拖动它,您需要:

  • touchesBegan中,保存起始locationInView以及&#34;原始位置&#34;拖动的对象;

  • touchesMoved中,获取新的locationInView,计算其与原始locationInView之间的差值(&#34;翻译&#34;),将其添加到已保存的原始位置&#34;视图,并使用它来更新视图。

这样,当您在屏幕上拖动对象时,对象将用手指跟踪100%。


例如,您可以:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.touchBeganLocation = [[touches anyObject] locationInView:self];
    self.originalObjectPoint = self.objectPoint;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGPoint location = [[touches anyObject] locationInView:self];
    CGPoint translation = CGPointMake(location.x - self.touchBeganLocation.x, location.y - self.touchBeganLocation.y);
    self.objectPoint = CGPointMake(self.originalObjectPoint.x + translation.x, self.originalObjectPoint.y + translation.y);
    [self setNeedsDisplay];
}

可能不用说,您需要属性来跟踪这两个新的CGPoint值:

@property (nonatomic) CGPoint originalObjectPoint;
@property (nonatomic) CGPoint touchBeganLocation;

坦率地说,我可能会使用手势识别器,但这是使用touchesBegantouchesMoved进行拖动的示例。