如何在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
相关产品推荐
相关产品推荐

