You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift图片添加文本:文本对齐、背景透明度及前置图片实现问题

Swift 图片添加文本的问题解决

以下是用于给图片添加文本的Swift代码:

for (index, textData) in textDataCurrentImg.enumerated() {
    let textColor = textData.fontColor
    let textFont = UIFont(name: textData.font.fontName, size: textData.fontSize)!
    let padding: CGFloat = 10.0
    let breakdText = textData.addBreaks(in: textData.text, with: textFont, forWidth: newImage.size.width, padding: Int(textData.xPosition))
    
    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(newImage.size, false, scale)
    
    // 绘制原图
    newImage.draw(in: CGRect(origin: CGPoint.zero, size: newImage.size))
    
    let textFontAttributes: [NSAttributedString.Key : Any] = [
        NSAttributedString.Key.font: textFont,
        NSAttributedString.Key.foregroundColor: textColor,
    ]
    
    if let backColor = textData.backColor {
        // 绘制文本背景矩形
        let textSize = breakdText.size(withAttributes: textFontAttributes)
        let backgroundRect = CGRect(
            origin: CGPoint(x: textData.xPosition - padding, y: textData.yPosition - padding),
            size: CGSize(width: textSize.width + 2 * padding, height: textSize.height + 2 * padding)
        )
        backColor.setFill()
        UIRectFill(backgroundRect)
    }
    
    // 在背景上绘制文本
    breakdText.draw(in: CGRect(x: textData.xPosition, y: textData.yPosition, width: newImage.size.width, height: newImage.size.height), withAttributes: textFontAttributes)
    
    newImage = UIGraphicsGetImageFromCurrentImageContext() ?? image
    UIGraphicsEndImageContext()
}

实现过程中遇到三个问题,对应的解决方法如下:

1. 文本对齐不生效问题

尝试添加段落样式但未达到预期效果:

let textFontAttributes: [NSAttributedString.Key : Any] = [
    NSAttributedString.Key.font: textFont,
    NSAttributedString.Key.foregroundColor: textColor,
    NSAttributedString.Key.paragraphStyle: {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = textData.textAlignment
        return paragraphStyle
    }()
]

解决方法:

问题出在文本绘制的CGRect范围设置错误。draw(in:)会根据段落样式在指定rect内对齐文本,但原代码设置的width是整个图片宽度,导致对齐效果不明显。正确做法是根据文本实际尺寸和对齐方式调整绘制rect:

// 计算文本实际尺寸
let textSize = breakdText.size(withAttributes: textFontAttributes)
var drawRect = CGRect(x: textData.xPosition, y: textData.yPosition, width: textSize.width, height: textSize.height)

// 根据对齐方式调整x坐标
switch textData.textAlignment {
case .right:
    drawRect.origin.x = newImage.size.width - textSize.width - textData.xPosition
case .center:
    drawRect.origin.x = (newImage.size.width - textSize.width) / 2
case .left, .justified, .natural:
    break // 保持原有xPosition
}

// 绘制文本
breakdText.draw(in: drawRect, withAttributes: textFontAttributes)

同时确保addBreaks方法未强制修改文本换行逻辑,避免干扰段落样式的对齐效果。

2. 文本背景透明度实现

直接利用已有代码片段,替换原有背景色即可:

if let backColor = textData.backColor {
    let alpha: CGFloat = 0.5
    let alphaColor = backColor.withAlphaComponent(alpha)
    let textSize = breakdText.size(withAttributes: textFontAttributes)
    let backgroundRect = CGRect(
        origin: CGPoint(x: textData.xPosition - padding, y: textData.yPosition - padding),
        size: CGSize(width: textSize.width + 2 * padding, height: textSize.height + 2 * padding)
    )
    alphaColor.setFill()
    UIRectFill(backgroundRect)
}

注意:已设置UIGraphicsBeginImageContextWithOptions(newImage.size, false, scale)(第二个参数为false,支持透明),因此透明背景可正常显示。

3. 文本前添加图片(当textData.isLocation为true时)

解决方法:

将图片作为NSTextAttachment嵌入富文本,实现图片与文本的一体化绘制,同时背景矩形自动包含图片区域:

// 构建带图片的富文本
var attributedText = NSMutableAttributedString(string: "")

if textData.isLocation {
    // 加载位置图标(替换为你的图片资源)
    let locationImage = UIImage(named: "location_icon")!
    let attachment = NSTextAttachment()
    attachment.image = locationImage
    // 调整图片大小与文本基线对齐
    let imageSize = CGSize(width: textFont.pointSize * 1.2, height: textFont.pointSize * 1.2)
    attachment.bounds = CGRect(origin: CGPoint(x: 0, y: (textFont.capHeight - imageSize.height)/2), size: imageSize)
    
    // 添加图片附件和空格分隔
    attributedText.append(NSAttributedString(attachment: attachment))
    attributedText.append(NSAttributedString(string: " "))
}

// 添加原文本
attributedText.append(NSAttributedString(string: breakdText, attributes: textFontAttributes))

// 计算包含图片的富文本尺寸
let fullTextSize = attributedText.boundingRect(with: CGSize(width: newImage.size.width - textData.xPosition*2, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil).size

// 绘制背景(如果需要)
if let backColor = textData.backColor {
    let alpha: CGFloat = 0.5
    let alphaColor = backColor.withAlphaComponent(alpha)
    let backgroundRect = CGRect(
        origin: CGPoint(x: textData.xPosition - padding, y: textData.yPosition - padding),
        size: CGSize(width: fullTextSize.width + 2 * padding, height: fullTextSize.height + 2 * padding)
    )
    alphaColor.setFill()
    UIRectFill(backgroundRect)
}

// 绘制富文本
attributedText.draw(in: CGRect(x: textData.xPosition, y: textData.yPosition, width: fullTextSize.width, height: fullTextSize.height))

此方式可让图片与文本保持基线对齐,背景矩形自动适配图片和文本的整体区域,无需手动调整位置。

内容的提问来源于stack exchange,提问作者Dhruvisha Joshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:12:14