1

I want the text to always be vertically centered. It doesn't work for some specific fonts such as "DamascusSemiBold", What is the solution?

    let label = VerticalLabel(frame: CGRect(x: 10, y: 100, width: 300, height: 50))
    label.layer.borderColor = UIColor.red.cgColor
    label.layer.borderWidth = 1
    label.text = "Text Sticker"
    label.font = UIFont(name: "DamascusSemiBold", size: 30)
    label.numberOfLines = 0
    label.textColor = .white
    label.textAlignment = .center
    self.view.addSubview(label)


public override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
    var textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
    print(textRect, bounds)
    textRect.origin.y = bounds.origin.y + (bounds.size.height - textRect.size.height) * 0.5
    print(textRect)
    return textRect
}

public override func drawText(in rect: CGRect) {
    let actualRect = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
    super.drawText(in: actualRect)
}

It's not centered, just top!

I know there are a lot of threads similar to this, but I've read all of them (as far as I can tell) and haven't seen the same problem I'm having.

I'm trying to get all of the text to show in a label VERTICALLY.

Let me explain - Fonts are not always created the same way, so while their total height may be the same (24pts, for example). However, the Ascender and Descender vary widely - one font may be mostly above the baseline, while another is mostly below. Therefore, the same text, with different fonts may not always show in the same view/label.

The first is Helvetica-Bold 300pts. The second is Apple Gothic 300pts.

Notice how the bottom of the "g" is cut off with Helvetica (and many other fonts too - try it, you'll see).

So my issue is this: I'd like to be able to see the entire text, regardless of the font. If the text in the "Helvetica" example could be moved up (and centered) within the label, it would solve my problem. To make it easier, I only need to display a single line.

Unfortunately, none of the solutions I've seen involve the descenders and ascenders of the font and figuring out how to draw the text within a Rect and not have it cropped. Note that the "VerticalAlignment" solutions in various threads don't fix this particular problem.

I calculate boundRect for attributedString and update the frame of label, and center text vertically

super.drawText(in: rect.inset(by: UIEdgeInsets(top: -(font.ascender - font.capHeight), left: 0, bottom: font.descender, right: 0)))

Above code cuts descender even though center vertically, how can I center text vertically without cutting of ascender, descender? Screenshot Does anyone have any ideas or solutions for this?

GPIT
  • 13
  • 4
  • Damascus is an Arabic font. If you use Arabic characters - such as `label.text = "\u{069a} \u{069b} \u{069c} \u{069d} \u{069e} \u{069f}"` you'll see that those characters ***are*** vertically centered. – DonMag Sep 02 '22 at 15:45
  • Hope this will help you: https://stackoverflow.com/questions/1054558/vertically-align-text-to-top-within-a-uilabel – Bahtijar Hasani Sep 02 '22 at 19:12
  • It would help if you included some screen-cap images of what you're trying to do, and what's not working. – DonMag Sep 02 '22 at 20:48
  • Is this what you're going for? https://i.stack.imgur.com/PeUhx.png – DonMag Sep 02 '22 at 21:32
  • @DonMag Yup, it's just what I want to try. After resize label regarding to attribute text's size, center text vertically, horizontally. – GPIT Sep 02 '22 at 23:36
  • @GPIT - to center the text as you want, one approach is to get the bounding box of the ***glyphs*** and then offset the drawing. This is a pretty good starting point: https://stackoverflow.com/questions/21443625/core-text-calculate-letter-frame-in-ios – DonMag Sep 05 '22 at 15:12
  • https://stackoverflow.com/questions/16977895/how-to-center-text-in-uilabel-with-different-fonts I don't need to get the bound of the glyphs, just above link is what I want. – GPIT Sep 06 '22 at 02:05
  • @GPIT - I realize you're not trying to outline the glyphs... the idea is: Get the bounding box of the run of glyphs - which would define the y- and x-offsets - and then draw the glyphs centered using that bounding box: https://i.stack.imgur.com/OrS0V.png – DonMag Sep 06 '22 at 21:26

1 Answers1

0

f you have a label with longer text that will make more than one line, set numberOfLines to 0 (zero here means an unlimited number of lines).

label.numberOfLines = 0