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

如何在iOS Swift项目中垂直居中字符串的单个字符?

实现文本视觉垂直居中的解决方案

针对你遇到的UILabel中小写字母无法和数字视觉垂直居中的问题,以下是几种可行的实现方式:

一、自定义UILabel调整绘制区域

重写drawText(in:)方法,通过计算文本的实际视觉边界,手动调整绘制位置,让文本的视觉中心与Label中心对齐:

class VisualCenterLabel: UILabel {
    override func drawText(in rect: CGRect) {
        guard let text = text, let font = font else {
            super.drawText(in: rect)
            return
        }
        
        let attrString = NSAttributedString(string: text, attributes: [.font: font])
        let textBounds = attrString.boundingRect(
            with: CGSize(width: rect.width, height: .greatestFiniteMagnitude),
            options: [.usesLineFragmentOrigin, .usesFontLeading],
            context: nil
        )
        
        // 计算垂直偏移:抵消系统基线对齐带来的偏差
        let verticalOffset = (rect.height - textBounds.height) / 2 - textBounds.minY
        let adjustedRect = rect.offsetBy(dx: 0, dy: verticalOffset)
        
        super.drawText(in: adjustedRect)
    }
}

使用时直接将Storyboard中的UILabel类改为VisualCenterLabel即可。

二、CoreText手动控制排版

如果需要更精细的控制,直接用CoreText绘制文本,利用光学边界(Optical Bounds)获取字符的真实视觉范围:

class CoreTextVisualCenterView: UIView {
    var displayText: String? {
        didSet { setNeedsDisplay() }
    }
    var displayFont: UIFont = .systemFont(ofSize: 20) {
        didSet { setNeedsDisplay() }
    }
    var displayColor: UIColor = .black {
        didSet { setNeedsDisplay() }
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        guard let text = displayText else { return }
        
        let attrString = NSMutableAttributedString(string: text)
        attrString.addAttribute(.font, value: displayFont, range: NSRange(location: 0, length: text.count))
        attrString.addAttribute(.foregroundColor, value: displayColor, range: NSRange(location: 0, length: text.count))
        
        let framesetter = CTFramesetterCreateWithAttributedString(attrString as CFAttributedString)
        let path = CGPath(rect: bounds, transform: nil)
        let frame = CTFramesetterCreateFrame(framesetter, CFRange(location: 0, length: 0), path, nil)
        
        guard let lines = CTFrameGetLines(frame) as? [CTLine], let context = UIGraphicsGetCurrentContext() else { return }
        
        let lineOrigins = CTFrameGetLineOrigins(frame, CFRange(location: 0, length: lines.count), nil)
        context.textMatrix = .identity
        context.translateBy(x: 0, y: bounds.height)
        context.scaleBy(x: 1, y: -1)
        
        for (index, line) in lines.enumerated() {
            let lineBounds = CTLineGetBoundsWithOptions(line, .useOpticalBounds)
            // 计算让视觉中心对齐的偏移量
            let verticalOffset = (bounds.height - lineBounds.height) / 2 - lineBounds.origin.y
            let adjustedOrigin = CGPoint(x: lineOrigins[index].x, y: lineOrigins[index].y + verticalOffset)
            
            context.textPosition = adjustedOrigin
            CTLineDraw(line, context)
        }
    }
}

这种方式完全脱离系统UILabel的排版逻辑,直接控制每个字符的绘制位置,确保视觉中心对齐。

三、第三方库推荐

如果不想手动实现,可以考虑成熟的文本排版库:

  • YYText:功能全面的富文本渲染库,支持自定义基线调整和视觉对齐规则,能快速实现需求。
  • TextAttributes:轻量级的文本属性工具库,可以通过调整基线偏移量实现视觉居中效果。

内容的提问来源于stack exchange,提问作者Ronnie de Rakker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:10:48