Ignore Ascender and Descender when centering UILabel vertically?

前端 未结 3 1400
天命终不由人
天命终不由人 2021-01-12 17:08

I’m using AutoLayout to position some labels in the vertical centre of a cell. The text is in all-caps, but the UILabel in question, even when sizeToFit

3条回答
  •  借酒劲吻你
    2021-01-12 17:49

    Thanks, Abhinit, for your answer.

    I was also looking for this so I would like to post here the exact constraints you need to apply to align texts to your liking.

    This image from Wikipedia shows the different size sections of a font.

    So, there are many ways to align a label depending on whether you want to align to the ascender height, the cap height, the x-height, baseline or descender height.

    Let's say you have a label containing text in caps like "HELLO" and you want to align with viewAbove to cap height and align with viewBelow to baseline.

    You would do:

    let font = label.font
    let ascenderDelta = font.ascender - font.capHeight
    
    LayoutHelper()
        .addViews([
            "label":label, "viewAbove":viewAbove, "viewBelow":viewBelow
        ])
        .withMetrics(["ascenderDelta":ascenderDelta])
        .addConstraints([
    
            // -- Here the constraints to align to cap height --
            "X:label.top == viewAbove.bottom - ascenderDelta",
            "X:label.baseline == viewBelow.top",
    
            ...other constraints...
        ])
    

    Note: in the example I'm using my utility class LayoutHelper, but I hope the idea is clear.

    About an "auto-aligning" label:

    I will think about making an "intelligent" label that adjusts to the appropriate line depending on whether it contains descenders, ascenders, caps, etc.

    You could do it using negative insets in drawTextInRect(like here but, for example, using insets = {-ascenderDelta, 0, font.descender, 0}). But that would crop any ascenders/descenders in case you had. I would prefer to align to caps without cropping any possible ascender.

提交回复
热议问题