CodeV

1.7-使用UIKit上下文绘图

UIKit简化了创建和管理上下文的任务。建立一个新的图像或PDF上下文只需要一行,另一行进行包装结束上下文。在这些行之间,您可以自由地执行任何绘图请求。这些都将被应用于当前的上下文。

清单 1-6 使用与清单 1-5 相同的绘图函数,并产生相同的图像结果。但是,这些更新不是绘制到自定义的Quartz上下文,而是绘制到一个新建立的图像上下文。为了在Quartz和UIKit之间进行桥接,调用UIGraphicsGetCurrentContext(),这会返回一个CGContextRef类型的对象,使您可以在Core Graphics绘图调用中使用该值。

需要指出的是,当您将清单 1-6 中的代码行数与清单 1-4 和 1-5 的组合进行比较时,您会看到使用UIKit绘图更简单。

清单 1-6 使用UIKit中图像上下文绘制一个椭圆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Establish the image context
UIGraphicsBeginImageContextWithOptions(targetSize, isOpaque, 0.0);

// Retrieve the current context
CGContextRef context = UIGraphicsGetCurrentContext();

// Perform the drawing
CGContextSetLineWidth(context, 4);
CGContextSetStrokeColorWithColor(context,[UIColor grayColor].CGColor);
CGContextStrokeEllipseInRect(context, rect); // Retrieve the drawn image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

// End the image context
UIGraphicsEndImageContext();

你可以在启动任何图像或PDF上下文后调用UIGraphicsGetCurrentContext()。 这个上下文会一直持续到你调用UIGraphicsEndImageContext()UIGraphicsEndPDFContext()

类似地,你可以通过调用UIGraphicsPushContext(context)在这些例程之外建立一个上下文。清单 1-4 中提供了一个手动构建的Quartz上下文的范例,并用UIGraphicsPopContext()结束这个上下文。这些调用都会在UIKit上下文堆栈中建立你正在绘制的上下文。压栈和出栈可以根据需要临时在绘制目标之间切换。

否则,在显式上下文环境之外,当前上下文是nil,有一个例外:在调用drawRect:方法时,视图将上下文压入UIKit图形上下文栈中。因此,如果你正在实现drawRect:方法,你可以假设总是有一个有效的上下文供你使用:

1
2
3
4
- (void) drawRect: (CGRect) rect{
// Perform drawing here
// If called, UIGraphicsGetCurrentContext()
// returns a valid context }

UIKit当前上下文

在Quartz中,几乎每个绘图函数都需要一个上下文参数。你需要明确地将上下文参数传递给每个函数。例如,你可能想设置画笔颜色为灰色:

1
CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);

在UIKit绘图中,上下文是从运行时条件下建立的。如清单1-7。此代码再次构建了如图1-5所示的相同的4像素宽的椭圆形。然而,这个代码并没有明确地引用上下文。

此代码清单创建一个椭圆路径。它将线宽设置为4,将描边颜色设为灰色,然后描绘路径。 在每个步骤中,以您的名义访问上下文。与清单 1-6 一样,相同的灰色应用于当前上下文,但并未指定上下文。如下清单 1-7 没有提到上下文。

清单 1-7 使用UIKit图形上下文绘制椭圆

1
2
3
4
5
// Stroke an ellipse using a Bezier path
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];
path.lineWidth = 4;
[[UIColor grayColor] setStroke];
[path stroke];

UIKit拥有一个图形上下文栈。它将绘制操作应用于该栈顶部的任何上下文。即:将最顶层上下文状态线宽更新为4和描边颜色更新为灰色。

那么如何将Core Graphics上下文与UIKit集成?UIKit提供了两个关键功能,本章前面已经简要提到:

  • 通过调用UIGraphicsPushContext(context)手动push上下文。此函数将上下文压入到UIKit栈顶,并设置要绘制的活动上下文。
  • 通过调用UIGraphicsPopContext()来保持栈的平衡。这会将当前上下文从UIKit堆栈中弹出,将活动上下文重置为堆栈中的下一个项目或将其重置为nil。

通过使用这些调用,可以将清单 1-7 中的基于Bezier路径的绘图代码嵌入到清单 1-3 中的基于Quartz的上下文中。这种方法将UIKit绘图连接到了Core Graphics上下文中创建和管理。

总而言之,将Core Graphics上下文与UIKit绘图混合的步骤如下:

  1. 创建一个Core Graphics上下文。
  2. 使用UIGraphicsPushContext()将上下文压入栈中。
  3. 使用可以推断当前上下文的UIKit绘图调用和显式使用上下文的Quartz调用组合。
  4. (可选地,将上下文内容检索生成图像。)
  5. 使用UIGraphicsPopContext()将上下文出栈。
  6. 释放上下文的内存空间。

如果您尝试在没有活动上下文的情况下使用UIKit绘制,您会收到警告,上下文无效。


本文翻译自《iOS Drawing Practical UIKit Solutions》作者:Erica Sadun,翻译:Cheng Dong。如果觉得本书不错请购买支持正版:亚马逊购买传送门,本书所有源代码可在GitHub上下载。译者虽然力求做到信,达,雅,但是由于时间仓促加之译者水平十分有限,文中难免会出现不正确,不准确,词不达意,难于理解的地方,还望各位批评指正,共同进步,谢谢。转载请注明出处。