提问者:小点点

swift中文本的垂直对齐方式


如图所示,我有代码在屏幕上绘制文本。textalign函数仅支持水平对齐。现在,我要添加对垂直对齐的支持。有人能帮我一下吗?

代码

func textAlign(_ horizonalAlign: String, _ verticalAlign: String? = nil){
    settings.textAlignment = horizonalAlign
}

func text(_ str: String, _ x: CGFloat, _ y: CGFloat, _ x2: CGFloat? = nil, _ y2: CGFloat? = nil) {
    let fontSizeWidthRatio: CGFloat = 1.8
    let paragraphStyle = NSMutableParagraphStyle()
    
    var align: NSTextAlignment!
    switch settings.textAlignment {
    case LEFT:
        align = .left
    case RIGHT:
        align = .right
    case CENTER:
        align = .center
    default:
        align = .left
    }
    paragraphStyle.alignment = align
    
    let attributes: [NSAttributedString.Key: Any] = [
        .paragraphStyle: paragraphStyle,
        .font: UIFont(name: settings.textFont, size: settings.textSize)!,
        .foregroundColor: settings.fill.uiColor(),
        .strokeWidth: -settings.strokeWeight,
        .strokeColor: settings.stroke.uiColor(),
        .baselineOffset: y,
    ]
    
    if x2 == nil {
        str.draw(at: CGPoint(x: x, y: y), withAttributes: attributes)
    }else{
        str.draw(with: CGRect(x: x, y: y, width: (x2 != nil) ? x2! : width, height: (y2 != nil) ? y2! : height), options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
    }
}

共1个答案

匿名用户

正如Larme所建议的,你应该直接发布你的代码,这样更容易阅读,而且...复制粘贴:d

所以我的意见是,自己根据一个自定义枚举来计算字符串的rect:

    enum VerticalAlign {
    case top
    case center
    case bottom
}

当然,这意味着如果从cgpoint中绘制,则只能在cgrect中绘制,则不能使用这种对齐方式。

你的功能会变成这样:

    func text(_ str: String, _ x: CGFloat, _ y: CGFloat, _ x2: CGFloat? = nil, _ y2: CGFloat? = nil, _ verticalAlign: VerticalAlign) {

    // Add your paragrapheStyle and horizontal alignment here
    // ...
    // ...
    // ... and set your attributes
    let attributes: [NSAttributedString.Key: Any] = [
        .font: UIFont.systemFont(ofSize: 18.0),
        .foregroundColor: UIColor.red
    ]
    let hardcodedHeightValue: CGFloat = 20.0
    
    // Vertical alignment can be only used if you draw in rect (so in your example, its only if you have a width)
    if let width = x2 {
        let height = y2 ?? hardcodedHeightValue
        let size = str.size(withAttributes: attributes)
        let centeredRect: CGRect
        switch verticalAlign {
        case .top:
            centeredRect = CGRect(x: x,
                                  y: y,
                                  width: width,
                                  height: size.height)
        case .center:
            centeredRect = CGRect(x: x,
                                  y: y + height * 0.5 - size.height * 0.5,
                                  width: width,
                                  height: size.height)
        case .bottom:
            centeredRect = CGRect(x: x,
                                  y: y + height - size.height,
                                  width: width,
                                  height: size.height)
        }
        str.draw(in: centeredRect, withAttributes: attributes)

    } else {
        str.draw(at: CGPoint(x: x, y: y), withAttributes: attributes)
    }
}