iOS - Quartz 绘图问题 parent/child 视图
iOS - Quartz drawing issue with parent/child views
场景
我有两种看法。一个是 "parent" 视图,它包含一个进行绘图的 "child" 视图。我在接下来的代码中将 child 称为 QuartzView。 QuartzView 知道如何根据自己的上下文绘制正方形。
问题
当我告诉它 self
上的 QuartzView 绘制正方形时,它会按预期执行。当我使用 parent 视图告诉 QuartsView 在它的 self
上绘制一个正方形时,它会在屏幕左下角以预期大小的大约 1/5 绘制正方形。
问题
我假设这里存在一些 parent/child 或上下文问题,但我不确定它们是什么。如何让两个正方形以完全相同的大小绘制在完全相同的位置?
Parent ViewController
- (void)drawASquare {
// this code draws the "goofy" square that is smaller and off in the bottom left corner
x = qv.frame.size.width / 2;
y = qv.frame.size.height / 2;
CGPoint center = CGPointMake(x, y);
[qv drawRectWithCenter:center andWidth:50 andHeight:50 andFillColor:[UIColor blueColor]];
}
Child QuartzView
- (void)drawRect:(CGRect)rect
{
self.context = UIGraphicsGetCurrentContext();
UIColor *color = [UIColor colorWithRed:0 green:1 blue:0 alpha:0.5];
// this code draws a square as expected
float w = self.frame.size.width / 2;
float h = self.frame.size.height / 2;
color = [UIColor blueColor];
CGPoint center = CGPointMake(w, h);
[self drawRectWithCenter:center andWidth:20 andHeight:20 andFillColor:color];
}
- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
CGContextSetFillColorWithColor(self.context, color.CGColor);
CGContextSetRGBStrokeColor(self.context, 0.0, 1.0, 0.0, 1);
CGRect rectangle = CGRectMake(center.x - w / 2, center.x - w / 2, w, h);
CGContextFillRect(self.context, rectangle);
CGContextStrokeRect(self.context, rectangle);
}
备注
- 两个方块的不透明度相同
- 我关闭了 "Autoresize subviews" 没有明显的区别
view.contentScaleFactor = [[UIScreen mainScreen] scale];
没有帮助
编辑
我注意到当从左下角开始绘制 parent 时,正方形的 x/y 值是 0,0,而通常 0,0 是左上角。
I assume there's some parent/child or context issues here but I'm not sure what they are. How can I get both squares to draw in the exact same place at the exact same size?
您通常不需要担心 -drawRect:
方法中的图形上下文,因为 Cocoa Touch 会在调用 -drawRect:
之前为您设置上下文。但是视图控制器中的 -drawASquare
方法调用 -drawRectWithCenter:...
以在正常绘图过程之外进行绘制,因此没有为您的视图设置上下文。您真的应该让视图在 -drawRect:
中进行绘制。如果您的视图控制器想要重绘视图,它应该调用 -setNeedsDisplay
,例如:
[qv setNeedsDisplay];
这会将视图添加到绘图列表中,图形系统会设置图形上下文并为您调用视图的 -drawRect:
。
I'm noticing that the x/y values of the square when drawn the parent starting from the bottom left as 0,0 whereas normally 0,0 would be the top left.
UIKit 和 Core Animation 使用左上原点,但 Core Graphics (a.k.a.Quartz) 通常使用左下原点。文档说:
The default coordinate system used by Core Graphics framework is LLO-based.
来自 UIGraphicsGetCurrentContext()
的 return 值仅在 drawRect
方法内部有效。您不能也不得在任何其他方法中使用该上下文。所以 self.context
属性 应该只是一个局部变量。
在 drawRectWithCenter
方法中,您应该将所有参数存储在属性中,然后使用 [self setNeedsDisplay]
请求视图更新。这样,框架将使用新信息调用 drawRect
。 drawRectWithCenter
方法应该看起来像这样
- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
self.showCenter = center;
self.showWidth = w;
self.showHeight = h;
self.showFillColor = color;
[self setNeedsDisplay];
}
当然,drawRect
函数需要获取该信息,并进行适当的绘图。
场景
我有两种看法。一个是 "parent" 视图,它包含一个进行绘图的 "child" 视图。我在接下来的代码中将 child 称为 QuartzView。 QuartzView 知道如何根据自己的上下文绘制正方形。
问题
当我告诉它 self
上的 QuartzView 绘制正方形时,它会按预期执行。当我使用 parent 视图告诉 QuartsView 在它的 self
上绘制一个正方形时,它会在屏幕左下角以预期大小的大约 1/5 绘制正方形。
问题
我假设这里存在一些 parent/child 或上下文问题,但我不确定它们是什么。如何让两个正方形以完全相同的大小绘制在完全相同的位置?
Parent ViewController
- (void)drawASquare {
// this code draws the "goofy" square that is smaller and off in the bottom left corner
x = qv.frame.size.width / 2;
y = qv.frame.size.height / 2;
CGPoint center = CGPointMake(x, y);
[qv drawRectWithCenter:center andWidth:50 andHeight:50 andFillColor:[UIColor blueColor]];
}
Child QuartzView
- (void)drawRect:(CGRect)rect
{
self.context = UIGraphicsGetCurrentContext();
UIColor *color = [UIColor colorWithRed:0 green:1 blue:0 alpha:0.5];
// this code draws a square as expected
float w = self.frame.size.width / 2;
float h = self.frame.size.height / 2;
color = [UIColor blueColor];
CGPoint center = CGPointMake(w, h);
[self drawRectWithCenter:center andWidth:20 andHeight:20 andFillColor:color];
}
- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
CGContextSetFillColorWithColor(self.context, color.CGColor);
CGContextSetRGBStrokeColor(self.context, 0.0, 1.0, 0.0, 1);
CGRect rectangle = CGRectMake(center.x - w / 2, center.x - w / 2, w, h);
CGContextFillRect(self.context, rectangle);
CGContextStrokeRect(self.context, rectangle);
}
备注
- 两个方块的不透明度相同
- 我关闭了 "Autoresize subviews" 没有明显的区别
view.contentScaleFactor = [[UIScreen mainScreen] scale];
没有帮助
编辑
我注意到当从左下角开始绘制 parent 时,正方形的 x/y 值是 0,0,而通常 0,0 是左上角。
I assume there's some parent/child or context issues here but I'm not sure what they are. How can I get both squares to draw in the exact same place at the exact same size?
您通常不需要担心 -drawRect:
方法中的图形上下文,因为 Cocoa Touch 会在调用 -drawRect:
之前为您设置上下文。但是视图控制器中的 -drawASquare
方法调用 -drawRectWithCenter:...
以在正常绘图过程之外进行绘制,因此没有为您的视图设置上下文。您真的应该让视图在 -drawRect:
中进行绘制。如果您的视图控制器想要重绘视图,它应该调用 -setNeedsDisplay
,例如:
[qv setNeedsDisplay];
这会将视图添加到绘图列表中,图形系统会设置图形上下文并为您调用视图的 -drawRect:
。
I'm noticing that the x/y values of the square when drawn the parent starting from the bottom left as 0,0 whereas normally 0,0 would be the top left.
UIKit 和 Core Animation 使用左上原点,但 Core Graphics (a.k.a.Quartz) 通常使用左下原点。文档说:
The default coordinate system used by Core Graphics framework is LLO-based.
来自 UIGraphicsGetCurrentContext()
的 return 值仅在 drawRect
方法内部有效。您不能也不得在任何其他方法中使用该上下文。所以 self.context
属性 应该只是一个局部变量。
在 drawRectWithCenter
方法中,您应该将所有参数存储在属性中,然后使用 [self setNeedsDisplay]
请求视图更新。这样,框架将使用新信息调用 drawRect
。 drawRectWithCenter
方法应该看起来像这样
- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
self.showCenter = center;
self.showWidth = w;
self.showHeight = h;
self.showFillColor = color;
[self setNeedsDisplay];
}
当然,drawRect
函数需要获取该信息,并进行适当的绘图。