【问题标题】:The movement of view with applied transformation on iPad Air (with retina display)在 iPad Air 上应用变换的视图移动(带有视网膜显示)
【发布时间】:2014-10-13 15:27:17
【问题描述】:

如果我对视图应用转换,则 iPad Air 上的视图移动会出现延迟。它看起来像 CALayer 中的隐式动画。 我创建了测试project。它应该在 iPad 模拟器上执行。 这是我用于应用转换的代码:

CGAffineTransform transform = CGAffineTransformIdentity;
if (_transformSwitch.on)
{
    transform = CGAffineTransformRotate(CGAffineTransformMakeScale(2.0, 2.0), M_PI / 3.0);
}

self.frameView.transform = transform;

这是我用于应用移动的代码:

CGPoint transition = [_panRecognizer translationInView:self.view];
CGPoint newCenter = CGPointMake(_startCenter.x + transition.x, _startCenter.y + transition.y);
self.frameView.center = newCenter;

如何通过应用变换移动视图并避免动画?

UPD 我找到了一个按计时器调用移动的解决方案,但是如果我用手指移动帧,我的动画就有问题。 我设置了视图的中心,并用 [CATransaction begin] [CATransaction commit] 包裹它:

[CATransaction begin];
[CATransaction setValue:@(YES) forKey:kCATransactionDisableActions];

_destinationIndicatorView.center = center;
self.frameView.center = center;

[CATransaction commit];

我找到了奇怪的解决方案,但我想知道为什么它是有效的解决方案? 我添加到这个方法 setNeedsDisplay,它解决了我的问题。 (如果我使用 drawRect 方法在我的屏幕上添加任何视图,并在它的视图上调用 setNeedsDisplay,它也解决了我的问题):

[CATransaction begin];
[CATransaction setValue:@(YES) forKey:kCATransactionDisableActions];

_destinationIndicatorView.center = center;
[self.frameView setNeedsDisplay];

self.frameView.center = center;

[CATransaction commit];

我已经更新了我的项目。

UPD2 这种滞后只发生在配备 Retina 显示屏的 iPad(例如 iPad Air)上。我制作了小视频来说明问题:https://yadi.sk/i/rAneCEFmjjEej

【问题讨论】:

  • 似乎有什么问题?
  • 您可以关闭滑块附近的开关并用手指移动带有传单的框架。如果您快速移动手指,则框架将在您的手指后面。
  • 快速移动手指时画面中心位置的问题。为了获得更多效果,您可以更改 line transform = CGAffineTransformRotate(CGAffineTransformMakeScale(2.3, 2.3), M_PI / 3.0);转换 = CGAffineTransformRotate(CGAffineTransformMakeScale(10.0, 10.0), M_PI / 3.0);
  • 我已经更新了项目。

标签: ios uiview cgaffinetransform ipad


【解决方案1】:

我认为您可以将更改包装在此代码中:

[CATransaction begin];
[CATransaction disableActions];

// Your changes to the UI elements...

[CATransaction commit];

【讨论】:

  • 你打开我的项目了吗?
  • 是的,我找到了解决方案,但不明白为什么会起作用
【解决方案2】:

好的,我玩过你的项目,发现有两件事与你预期的不同:

第一个是drawRect:FrameView

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
}

来自苹果:

这个方法的默认实现什么都不做。子类 使用 Core Graphics 和 UIKit 等技术来绘制他们的 视图的内容应该覆盖这个方法并实现它们的绘图 那里的代码。如果您的视图集,则不需要覆盖此方法 它的内容以其他方式。例如,您不需要覆盖 如果您的视图只显示背景颜色或者您的 view 直接使用底层对象设置其内容。

第二个是错误的(根据文档,它是正确的,见下文)FrameView 上覆盖的- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event 的返回值:您返回nil(如CALayerDelegate 参考中所述)而CoreAnimation,在事实上,期望NSNull 的实例(在阅读CALayer 类参考时可能会假设)。由于文档中存在冲突,您的操作导致了意外结果。我说的是thisthis

附:结果,我在不使用CATransaction 的情况下让它工作。不幸的是,我手头没有 Retina iPad,所以请查看我对您的 GitHub 项目的更改(我将创建一个包含我所有更改的拉取请求)并判断它是否解决了意外动画(假设已解决)问题和拖拽的延迟(需要在真正的 iPad 上检查性能问题)。

【讨论】:

  • 很好,我们可以从FrameView中删除空的drawRect方法。但是什么都没有改变,我们应该调用 setNeedsDisplay,以避免隐式动画。关于 NSNull 你是对的(这个勘误,我没看到),但它相当于 CATransaction 块:developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…
  • 我认为,没有 drawRect 方法调用 setNeedsDisplay 在视图上什么都不做。但是图层没有明确的绘制矩形,因此 setNeedsDisplay 可以使用任何计时器。
  • 如果不了解动画机制,我们就无法创建正确的好解决方案。可能是bug?
  • @AndrewRomanov,我已经通过一些新的性能调整尝试修改了我的更改。请检查这些。
  • 视频:yadi.sk/i/Dk-PHpjDjkGpv 我认为,使用光栅化是个好主意,我之前尝试过,但没有解决问题(在我使用 scale == 2.0 之前)。如果规模越大,问题就越明显。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多