Swift:如何在CoreGraphics上下文的UIImageView中正确绘制文本?
问题分析与解决方案
你的核心问题是绘制完成后未将生成的新图像赋值给UIImageView的image属性,导致文本无法显示;部分场景下的覆盖问题则是因为没有保留原有绘制内容或上下文使用不当。以下是具体修正方案:
关键问题拆解
- 第一段代码:开启上下文并绘制了原有内容和文本,但最终没有把上下文生成的图像赋值给
canvas.image,所以绘制结果从未显示在UIImageView上。 - 第二段代码:冗余嵌套了
UIGraphicsBeginImageContext和UIGraphicsImageRenderer,且未将renderer生成的图像赋值给UIImageView,同时固定的512x512尺寸可能与画布不匹配。
修正后的代码示例
方案1:基于UIGraphicsBeginImageContext的实现
func drawSegmentLength(on canvas: UIImageView, value: String, at coordinates: CGPoint) { let canvasSize = canvas.frame.size // 开启Retina适配的上下文,避免绘制内容模糊 UIGraphicsBeginImageContextWithOptions(canvasSize, false, UIScreen.main.scale) // 先绘制原有内容,保留之前的点、线等几何元素 canvas.image?.draw(in: CGRect(origin: .zero, size: canvasSize)) // 设置文本属性 let font = UIFont(name: "Helvetica", size: 12)! let textStyle = NSMutableParagraphStyle() textStyle.alignment = .center let textAttributes: [NSAttributedString.Key: Any] = [ .font: font, .paragraphStyle: textStyle, .foregroundColor: UIColor.black ] // 计算文本绘制区域(若需顶部对齐坐标点,可调整y值为coordinates.y - font.capHeight) let textRect = CGRect( x: coordinates.x, y: coordinates.y, width: 100, height: font.lineHeight ) value.draw(in: textRect.integral, withAttributes: textAttributes) // 生成新图像并更新UIImageView let newCanvasImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() canvas.image = newCanvasImage }
方案2:基于UIGraphicsImageRenderer的实现(更简洁的现代API)
override func draw(_ canvas: UIImageView, isRed: Bool, value: String, coordinates: CGPoint) { let canvasSize = canvas.frame.size let renderer = UIGraphicsImageRenderer(size: canvasSize) let newCanvasImage = renderer.image { ctx in // 保留原有绘制内容 canvas.image?.draw(in: CGRect(origin: .zero, size: canvasSize)) // 文本配置 let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = .center guard let font = UIFont(name: "HelveticaNeue-Thin", size: 12) else { return } let textAttributes: [NSAttributedString.Key: Any] = [ .font: font, .paragraphStyle: paragraphStyle, .foregroundColor: UIColor.black ] let textRect = CGRect(x: coordinates.x, y: coordinates.y, width: 100, height: 16) value.draw(with: textRect, options: .usesLineFragmentOrigin, attributes: textAttributes, context: nil) } // 更新UIImageView显示 canvas.image = newCanvasImage }
注意事项
- 若不需要保留原有绘制内容(即每次绘制都是全新画布),可删除
canvas.image?.draw(...)这一行。 - 文本的y坐标默认对应基线位置,若需让文本顶部与
coordinates.y对齐,需调整y值为coordinates.y - font.capHeight(capHeight是字体大写字母的高度)。 - 始终使用
UIGraphicsBeginImageContextWithOptions(而非UIGraphicsBeginImageContext),传入屏幕scale参数保证Retina屏幕下的清晰度。
内容的提问来源于stack exchange,提问作者Daniel Heath
相关产品推荐
相关产品推荐

