我的问题是:我有一个简单的块图像,我想制作一个网格。我在我的UIView中创建了一个CGPoints数组。然后我用了
blackImage = [UIImage imageNamed:@"black.png"];
然后
- (void)drawRect:(CGRect)rect {
for (int j = 0 ; j <= 11; j++)
{
for (int i = 0 ; i <= 7; i++)
{
[blackImage drawAtPoint: (CGPointFromString([[self.points objectAtIndex:j] objectAtIndex:i]))];
}
}
[whiteImage drawAtPoint:(CGPointMake((CGFloat)(floor((touchX+0.001)/40)*40), (CGFloat)(floor((touchY+0.001)/40))*40))];
// [whiteImage drawAtPoint:(CGPointMake(240.0, 320.0))];
}
TouchX和TouchY是用户触摸屏幕的CGPoints。所以我基本上在用户触摸的网格上显示不同的图像。
首先,问题是每次调用DrawRect时都会重绘整个屏幕。我希望能够保存状态(通过更改BOOL的数组?)并让用户在屏幕上拖动并更改多个图像。但是,当我在DrawRect之外时,我无法在UImage上使用“drawAtPoint”方法。 (抛出错误)。
无论如何,我开始研究CoreAnimation和Quartz文档,并且真的很困惑。我不确定我是否应该为每个砖块创建多个UIViews(似乎过多),或者是CALayers或CGLayers的网格......我认为这很简单,我想做什么......但我真的不明白图层,以及使用CALayer和CGLayer之间的区别。显然“所有UIViews都是层支持的”这是什么意思?
我对如何实现这一点感到很遗憾。我基本上想要在网格中交换图像,这样用户就可以在屏幕上“画画”并切换图像。
我尝试使用[self setNeedsDisplayinRect]实现此功能,并传入用户手指下的CGRect。然而,这仍然是在TouchesMoved中调用DrawRect,它给了我想要的效果,但在iPhone上却太慢了。使用CALayers是否有更有效的方法来实现相同的效果?我是Core Animation的新手,并不真正了解如何使用图层来解决这个问题。
答案 0 :(得分:2)
我认为在你的情况下,UIImage应该处理这个应用程序并提供良好的性能。问题似乎是您强制整个屏幕重绘以响应每条drawRect:
消息。传入的rect指定了您需要重绘的“脏区域”。任何其他绘图只是浪费时间。
同样,传递给视图的setNeedsDisplay:
的矩形是您特别想要失效的矩形。计算触摸周围的矩形并使其无效。 UIKit将(可能)联合多个脏的rects并发送一个drawRect:
。
我建议你执行以下优化:
drawRect:
(在调试器中)的脏矩形,如果它小于全屏编写代码,以确保只在脏矩形内重新绘制图像如果需要显示位图和1&amp; 2无法获得所需的性能,您将不得不求助于更低级别的技术。在SO上有很多例子包括this question。
答案 1 :(得分:1)
要仅使视图的一部分无效,请仅使用已更改的区域调用setNeedsDisplayInRect:
。如果多个rects已更改,您可以使用不同的rects调用它两次。
解决此问题的另一种方法是创建多个CALayer
并移动/隐藏它们。
此外,您不应该直接致电drawRect:
,而是使用setNeedsDisplay
。只要视图区域无效并且需要绘画,UIKit就会调用drawRect:
。
答案 2 :(得分:1)
77个离散图像作为CALayers或UIViews网格(假设您的图像只有几个像素宽)并不太麻烦,所以我建议采用这种方法。 UIViews并不比CALayers重,所以我要做的是构建一个离散的UIImageViews网格(假设您的黑色图像不仅仅是黑色,如果不是,您可以将标准的UIView的backgroundColor设置为黑色或白色)。如果您在视图中移动时不需要跟踪触摸,您甚至可以通过触摸处理来切换UIImageView的自定义子类中的视图图像,或者通过控制器中的委托方法。
这样,重新渲染的显示器的唯一部分将是正在改变的特定UIView。我推荐UIViews优于CALayers只是因为UIViews在视图层次结构中更容易放置。
为了清楚解释CALayers,UIViews等在iPhone上的交互方式,我建议您阅读“iPhone应用程序编程指南”的“视图架构和几何”部分中的“视图渲染架构”小节”