【问题标题】:UIPanGestureRecognizer - move view instantlyUIPanGestureRecognizer - 立即移动视图
【发布时间】:2012-12-25 05:55:08
【问题描述】:

我只需要它来根据平移手势移动一些视图。 问题是它不会立即发生,就像苹果地图一样,如果我将手指放在一个点上,然后快速移动到任何方向,视图会延迟移动,这意味着我将能够看到我的手指点,那是我不想要的。

可能由于硬件限制而无法实现,因为在模拟器中它可以正常工作。 或者也许有更好的方法我不知道。

谢谢。


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

【问题讨论】:

  • - (IBAction)pan:(UIPanGestureRecognizer *)sender { CGPoint center = [sender locationInView:sender.view]; self.myView.center = 中心; }
  • 对不起,我不知道如何保持缩进。
  • 这个视图是什么?如果相当复杂,您可以栅格化并查看是否可以解决问题。
  • 这个视图只有 2 个 UIImageView(其中一个 UIImageView 正在动画,只是缩放,像脉冲一样)。基本上 myView 与您在当前位置的地图上看到的带有脉动圆圈的蓝色球相同。我想要的是移动那个球,使它始终保持在用户的手指下方。所以当用户平移时应该永远看不到球的中心。
  • 跳动的动画,虽然不是标准操作的负担,但会对拖动整个东西产生实质性的影响。尝试暂停脉冲,看看行为是否有所改善。即使是像非光栅化阴影这样简单的事情也可能出人意料地出现问题。您需要简化事情(至少在平底锅期间)。另请参阅光栅化视图的示例(但也暂停脉冲动画)。

标签: ios ios6


【解决方案1】:

当我第一次回答时,我假设被拖动的视图有些复杂(例如,很大的 CALayer 阴影,计算量可能很大)。因此,我的原始答案如下。但在随后的cmet交流中,发现其中一个按钮有跳动的动画,这更有可能是问题所在。 animation should be suspended 在拖动视图时如果拖动性能不可接受。因此:

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

显然,这可以与下面讨论的图像光栅化相结合,但我会先尝试像上面那样暂停动画。


原答案:

如果您拖动的视图非常复杂,您可以尝试对其进行栅格化。

  1. QuartzCore.framework 添加到目标的"Link binary with libraries" 设置中。

  2. 然后将源调整为相应的光栅化。

如:

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

顺便说一句,我建议像这段代码一样保存originalCenter,这样如果你抓住被拖离中心一点的视图,它就不会突然跳到你身上。

【讨论】:

  • 我像你说的那样删除了动画并使用了光栅化,但仍然有延迟。
  • @RodrigoRuiz 两件事:首先,尝试暂时完全摆脱图像,看看性能如何。这建立了一个基线。 (设置背景颜色,以便您可以看到移动的视图,如果您不能看到它。)您会看到一些滞后,但它应该是合理的。其次,假设解决了它,然后看图像本身?是正在调整大小或重新缩放的大图像吗?或者它是一个与UIImageView/UIButton 完美匹配的漂亮小图像?它是按比例设置还是仅居中?
  • 我确实尝试只使用带有圆角的简单 UIView,但延迟仍然无法接受。
  • @RodrigoRuiz 我一直在玩这个,我总是看到一点滞后。我什至尝试更改layerturned off implicit animationsposition 属性,但我仍然看到了延迟。清楚地使用bringSubviewToFront 并确保您没有透明度会有所帮助,但我仍然看到我在所有内置应用程序中看到的同样适度的延迟。你说地图很好,但我在应用中看到的延迟与我在那里看到的一样。
  • @RodrigoRuiz 啊,对不起,我误解了你的地图。我能想象的唯一另一件事是,您可能可以做一些轻微的手,将对象拖到您前进的方向前一点(例如,不仅要考虑translation,还要考虑velocity,太),但玩弄它,它很有希望,但很难让它顺利。 (叹气。)
【解决方案2】:

在为中心点设置新值时尝试禁用动画。

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

如果这有帮助,您可以尝试使用更快的动画来平滑它。

您也可以尝试禁用动画,如下所述: Explicitly disabling UIView animation in iOS4+

很快:

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

一旦您设法在重新定位期间禁用所有动画,这取决于硬件和代码的速度。

【讨论】:

  • 我认为上面的代码没有效果。但我确实完全删除了动画,但仍然有同样的问题,视图的中心不跟随我的手指。我的表弟也用他的手机试了一下,他说它变得更好了(延迟更少),但是,如果你把手指移动得快一点,你仍然可以看到视图的中心。
  • 哦,你应该注意到你什么时候禁用了动画。动画视图将逐步移动,而不是平滑滑动。如果非动画视图仍然响应太慢,您很可能不得不让您的代码更快。请查看更新后的答案。
  • 澄清一下,我说的是禁用重新定位视图时出现的隐式运动动画。禁用该视图后,视图将始终立即转到最后一次触摸位置。好吧,不是立即,而是与处理事件和重绘一样快。如果速度不够快(可能是这种情况),您可以尝试预测未来的触摸位置并稍微提前移动视图。但这可能会变得复杂,最好是在始终轻微错误和大部分时间正确之间进行权衡(但当您不正确时会更加错误)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-06
  • 2022-11-12
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多