简体   繁体   English

UIPanGestureRecognizer - 立即移动视图

[英]UIPanGestureRecognizer - move view instantly

All I need it to move some view around based on pan gesture. 我只需要根据平移手势移动一些视图。 The problem is that it doesn't happen instantly, just like Apple Maps, if I put down my finger on one point, and move it fast to any direction, the view will move with a delay, meaning I will be able to see the point that I put my finger on, and that is what I don't want. 问题是,它不会像Apple Maps一样立即发生,如果我将手指放在一个点上并快速向任意方向移动,视图将延迟移动,这意味着我将能够看到指出我把手指放在上面,这就是我不想要的。

Maybe it is impossible due to hardware limitations since in the simulator it works fine. 也许这是不可能的,因为硬件限制,因为在模拟器中它工作正常。 Or maybe there is a better way that I don't know. 或者也许有一种我不知道的更好的方式。

Thank you. 谢谢。


- (IBAction)pan:(UIPanGestureRecognizer *)sender 
{
    CGPoint center = [sender locationInView:sender.view];
    self.myView.center = center; 
}

When I first answered, I was presuming that there was something complicated about the view being dragged (eg a large CALayer shadow, which can be computationally expensive). 当我第一次回答时,我以为拖动视图存在一些复杂的情况(例如,较大的CALayer阴影,在计算上可能会很昂贵)。 Hence my original answer below. 因此,下面是我的原始答案。 But in a subsequent exchange of comments, it has been discovered that one of the buttons had an pulsing animation, which is more likely to be the problem. 但是在随后的评论交流中,已经发现其中一个按钮具有脉冲动画,这更可能是问题。 The animation should be suspended during the dragging of the view if the dragging performance is not acceptable. 如果拖动性能不可接受,则应在拖动视图期间暂停动画 Thus: 从而:

#import <QuartzCore/QuartzCore.h>

- (IBAction)pan:(UIPanGestureRecognizer *)gesture
{
    static CGPoint originalCenter;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        originalCenter = gesture.view.center;
        [self pauseLayer:gesture.view.layer];
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        CGPoint translate = [gesture translationInView:gesture.view.superview];
        gesture.view.center = CGPointMake(originalCenter.x + translate.x, originalCenter.y + translate.y);
    }
    else if (gesture.state == UIGestureRecognizerStateEnded ||
             gesture.state == UIGestureRecognizerStateFailed ||
             gesture.state == UIGestureRecognizerStateCancelled)
    {
        [self resumeLayer:gesture.view.layer];
    }
}

-(void)pauseLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;
}

-(void)resumeLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer timeOffset];
    layer.speed = 1.0;
    layer.timeOffset = 0.0;
    layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    layer.beginTime = timeSincePause;
}

Clearly, this can be combined with the rasterization of the image, discussed below, but I would try suspending the animation, like above, first. 显然,这可以与下面讨论的图像光栅化相结合,但我会先尝试暂停动画,如上所述。


Original answer: 原始答案:

If your view being dragged is at all complicated, you could try rasterizing it. 如果您拖动的视图非常复杂,则可以尝试对其进行栅格化。

  1. Add QuartzCore.framework to your target's "Link binary with libraries" settings. QuartzCore.framework添加到目标的“使用库链接二进制文件”设置。

  2. And then adjust the source to rasterize accordingly. 然后相应地调整源光栅化。

Such as: 如:

#import <QuartzCore/QuartzCore.h>

- (IBAction)pan:(UIPanGestureRecognizer *)gesture
{
    static CGPoint originalCenter;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        originalCenter = gesture.view.center;
        gesture.view.layer.shouldRasterize = YES;
    }
    if (gesture.state == UIGestureRecognizerStateChanged)
    {
        CGPoint translate = [gesture translationInView:gesture.view.superview];
        gesture.view.center = CGPointMake(originalCenter.x + translate.x, originalCenter.y + translate.y);
    }
    if (gesture.state == UIGestureRecognizerStateEnded ||
        gesture.state == UIGestureRecognizerStateFailed ||
        gesture.state == UIGestureRecognizerStateCancelled)
    {
        gesture.view.layer.shouldRasterize = NO;
    }
}

As an aside, I'd suggest saving the originalCenter like this code does, so that if you grab the view being dragged a little off center, it won't jump jarringly on you. 顺便说一下,我建议像这样的代码一样保存originalCenter ,这样如果你抓住视图被拖离中心一点点,它就不会在你身上猛烈地跳跃。

Try disabling animations when you set the new value for the center point. 设置中心点的新值时,请尝试禁用动画。

- (IBAction)pan:(UIPanGestureRecognizer *)sender 
{
    CGPoint center = [sender locationInView:sender.view];
    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
    self.myView.center = center; 
    [CATransaction commit];
}

If that helps you could try to smooth it with faster animation. 如果这有助于你可以尝试用更快的动画来平滑它。

You could also try to disable the animations as described here: Explicitly disabling UIView animation in iOS4+ 您还可以尝试禁用动画,如下所述: 在iOS4 +中显式禁用UIView动画

Shortly: 不久:

- (IBAction)pan:(UIPanGestureRecognizer *)sender 
{
    CGPoint center = [sender locationInView:sender.view];
    [UIView setAnimationsEnabled:NO];
    self.myView.center = center; 
    [UIView setAnimationsEnabled:YES];
}

Once you manage to disable all animations during the repositioning, it's up to the speed of the hardware and your code. 一旦你设法在重新定位期间禁用所有动画,它就取决于硬件和代码的速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM