UIView:如何进行无损绘制?
我原来的问题:
我正在创建一个简单的绘图 应用程序并且需要能够 在我的
drawRect
中绘制现有的、先前绘制的内容。 在现有内容之上绘制的正确方法是什么 而不完全替换它?
根据此处和其他地方收到的答案,交易如下。
您应该准备好重新绘制 每当
drawRect
时整个矩形 叫做。您无法通过执行以下操作来阻止内容被删除:
[self setClearsContextBeforeDrawing: NO];
这只是对图形引擎的一个提示,让它为您预先清除视图是没有意义的,因为无论如何您可能都需要重新绘制整个区域。 它可能会阻止您的视图被自动删除,但您不能依赖它。
要在视图顶部绘制而不擦除,请在离屏位图上下文中进行绘制(系统永远不会清除该上下文)。然后在您的
drawRect
中,从此离屏复制屏幕缓冲区到视图。
示例:
- (id) initWithCoder: (NSCoder*) coder {
if (self = [super initWithCoder: coder]) {
self.backgroundColor = [UIColor clearColor];
CGSize size = self.frame.size;
drawingContext = [self createDrawingBufferContext: size];
}
return self;
}
- (CGContextRef) createOffscreenContext: (CGSize) size {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, size.width*4, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(context, 0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);
return context;
}
- (void)drawRect:(CGRect) rect {
UIGraphicsPushContext(drawingContext);
CGImageRef cgImage = CGBitmapContextCreateImage(drawingContext);
UIImage *uiImage = [[UIImage alloc] initWithCGImage:cgImage];
UIGraphicsPopContext();
CGImageRelease(cgImage);
[uiImage drawInRect: rect];
[uiImage release];
}
TODO:任何人都可以优化 drawRect
以便仅将(通常很小的)修改后的矩形区域用于副本吗?
My original question:
I'm creating a simple drawing
application and need to be able to
draw over existing, previously drawn content in mydrawRect
.
What is the proper way to draw on top of existing content
without entirely replacing it?
Based on answers received here and elsewhere, here is the deal.
You should be prepared to redraw the
entire rectangle wheneverdrawRect
is called.You cannot prevent the contents from being erased by doing the following:
[self setClearsContextBeforeDrawing: NO];
This is merely a hint to the graphics engine that there is no point in having it pre-clear the view for you, since you will likely need to re-draw the whole area anyway. It may prevent your view from being automatically erased, but you cannot depend on it.
To draw on top of your view without erasing, do your drawing to an off-screen bitmap context (which is never cleared by the system.) Then in your
drawRect
, copy from this off-screen buffer to the view.
Example:
- (id) initWithCoder: (NSCoder*) coder {
if (self = [super initWithCoder: coder]) {
self.backgroundColor = [UIColor clearColor];
CGSize size = self.frame.size;
drawingContext = [self createDrawingBufferContext: size];
}
return self;
}
- (CGContextRef) createOffscreenContext: (CGSize) size {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, size.width*4, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(context, 0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);
return context;
}
- (void)drawRect:(CGRect) rect {
UIGraphicsPushContext(drawingContext);
CGImageRef cgImage = CGBitmapContextCreateImage(drawingContext);
UIImage *uiImage = [[UIImage alloc] initWithCGImage:cgImage];
UIGraphicsPopContext();
CGImageRelease(cgImage);
[uiImage drawInRect: rect];
[uiImage release];
}
TODO: can anyone optimize the drawRect
so that only the (usually tiny) modified rectangle region is used for the copy?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在屏幕外图像中绘制所有内容并在绘制屏幕时简单地显示该图像是相当常见的。 您可以阅读: 创建位图图形上下文。
It is fairly common to draw everything in an offscreen image, and simply display this image when drawing the screen. You can read: Creating a Bitmap Graphics Context.
优化drawRect
试试这个:
之后你还应该在代码中注释这些行:
还创建了一个单独的问题,以确保这是最佳方式。
On optimizing drawRect
Try this:
After that you should also comment these lines in your code:
Also created a separate question to be sure that it's the optimal way.
这似乎是比我一直使用的更好的方法。 也就是说,在触摸事件中,我复制了即将更新的视图。 然后在 drawRect 中,我获取该图像并将其绘制到视图中,并同时更改其他视图。
但这似乎效率低下,但却是我想出的唯一方法。
This seems like a better method than I've been using. That is, in a touches event I make a copy of the view about to be updated. Then in drawRect I take that image and draw it to the view and make my other view changes at the same time.
But this seems inefficient but the only way I figured out how to do it.
这可以防止您的视图在完成drawRect之前被擦除:
另外,我发现最好在drawRect方法中完成所有绘图(除非您有充分的理由不这样做)。 与简单地绘制一次所有内容相比,在屏幕外绘制和传输需要更多时间并增加更多复杂性。
This prevents your view from being erased before drawRect is done:
Also, I find it is better to do all the drawing in the drawRect method (unless you have a good reason not to). Drawing offscreen and transferring takes more time and adds more complexity then simply drawing everything once.