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

如何实现两个UILabel基于第一行文本Y轴中心对齐(含SwiftUI方案)

解决方案:UILabel 第一行文本Y轴中心对齐

UIKit 实现方案

核心思路是计算每个Label第一行文本的中心偏移量,通过调整顶部约束让两个Label的第一行中心处于同一Y轴位置,适配任意字体字号。

关键步骤:

  • 利用字体的ascender(基线到字符顶部距离,正数)和descender(基线到字符底部距离,负数),计算第一行文本中心相对于Label顶部的偏移量
  • 动态调整两个Label的顶部约束常量,补偿偏移实现对齐

代码实现:

import UIKit

class FirstLineAlignedLabelsView: UIView {
    
    let label1 = UILabel()
    let label2 = UILabel()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupBasicViews()
        setupLayoutConstraints()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupBasicViews()
        setupLayoutConstraints()
    }
    
    private func setupBasicViews() {
        label1.numberOfLines = 0
        label2.numberOfLines = 0
        addSubview(label1)
        addSubview(label2)
        label1.translatesAutoresizingMaskIntoConstraints = false
        label2.translatesAutoresizingMaskIntoConstraints = false
    }
    
    private func setupLayoutConstraints() {
        // 基础布局约束
        let baseConstraints = [
            label1.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            label2.leadingAnchor.constraint(equalTo: label1.trailingAnchor, constant: 16),
            label2.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor, constant: -16),
            bottomAnchor.constraint(greaterThanOrEqualTo: label1.bottomAnchor, constant: 16),
            bottomAnchor.constraint(greaterThanOrEqualTo: label2.bottomAnchor, constant: 16)
        ]
        
        // 计算第一行中心偏移并设置顶部约束
        let offset1 = getFirstLineCenterOffset(for: label1.font)
        let offset2 = getFirstLineCenterOffset(for: label2.font)
        
        let topConstraints = [
            label1.topAnchor.constraint(equalTo: topAnchor, constant: -offset1),
            label2.topAnchor.constraint(equalTo: topAnchor, constant: -offset2)
        ]
        
        NSLayoutConstraint.activate(baseConstraints + topConstraints)
    }
    
    private func getFirstLineCenterOffset(for font: UIFont) -> CGFloat {
        // 第一行文本中心相对于Label顶部的偏移量
        let lineHeight = font.ascender - font.descender
        let centerFromTop = lineHeight / 2 - font.ascender
        return centerFromTop
    }
    
    // 动态更新文本和字体时调用
    func updateContent(text1: String, font1: UIFont, text2: String, font2: UIFont) {
        label1.text = text1
        label1.font = font1
        label2.text = text2
        label2.font = font2
        
        // 更新偏移量和约束
        let offset1 = getFirstLineCenterOffset(for: font1)
        let offset2 = getFirstLineCenterOffset(for: font2)
        
        label1.constraints.first { $0.firstAnchor == label1.topAnchor }?.constant = -offset1
        label2.constraints.first { $0.firstAnchor == label2.topAnchor }?.constant = -offset2
        
        layoutIfNeeded()
    }
}

SwiftUI 实现方案

通过自定义垂直对齐指南,结合字体属性计算第一行文本中心位置,实现灵活对齐。

代码实现:

import SwiftUI

struct FirstLineAlignedTextPair: View {
    let text1: String
    let font1: Font
    let text2: String
    let font2: Font
    
    var body: some View {
        HStack(alignment: .firstLineCenter, spacing: 16) {
            Text(text1)
                .font(font1)
                .alignmentGuide(.firstLineCenter) { dims in
                    calculateAlignmentOffset(for: dims, font: font1)
                }
            Text(text2)
                .font(font2)
                .alignmentGuide(.firstLineCenter) { dims in
                    calculateAlignmentOffset(for: dims, font: font2)
                }
        }
        .padding(16)
    }
    
    private func calculateAlignmentOffset(for dims: ViewDimensions, font: Font) -> CGFloat {
        guard let uiFont = UIFont(font: font) else {
            return dims[.firstBaseline] / 2
        }
        let lineHeight = uiFont.ascender - uiFont.descender
        let centerFromBaseline = lineHeight / 2
        return dims[.firstBaseline] - centerFromBaseline
    }
}

// 自定义第一行中心对齐指南
extension VerticalAlignment {
    private enum FirstLineCenter: AlignmentID {
        static func defaultValue(in context: ViewDimensions) -> CGFloat {
            context[.top]
        }
    }
    static let firstLineCenter = VerticalAlignment(FirstLineCenter.self)
}

// SwiftUI Font 转 UIFont 扩展
extension UIFont {
    convenience init?(font: Font) {
        let descriptor = font.fontDescriptor
        self.init(descriptor: descriptor, size: descriptor.pointSize)
    }
}

// 预览示例
struct FirstLineAlignedTextPair_Previews: PreviewProvider {
    static var previews: some View {
        FirstLineAlignedTextPair(
            text1: "小字号文本",
            font1: .caption,
            text2: "大字号文本\n支持多行自动换行\n内容动态变化",
            font2: .title
        )
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 16:10:29