-2

I have tried everything I found on StackOverflow but nothing worked really. I need to calculate boundingRect's height for any/random UIFont available.

The code is simple (I modified some of the code to be more readable):

let ps = NSMutableParagraphStyle()
ps.lineBreakMode = NSLineBreakMode.byWordWrapping
ps.alignment = NSTextAlignment.center
ps.lineSpacing = 0
ps.paragraphSpacingBefore = 0
ps.paragraphSpacing = 0

let myRandomFont = geMyRandomFont(name: randomFontName, size: myFontSize)
let attrParams = [
    NSAttributedString.Key.font: myRandomFont,
    NSAttributedString.Key.paragraphStyle: ps
    ] as [NSAttributedString.Key : Any]

let ns = NSString(string: text)
let toUseForDrawingBounds = ns.boundingRect(
    with: CGSize(width: boundsSize.width, height: .greatestFiniteMagnitude),
    options: [.usesLineFragmentOrigin, .usesFontLeading],
    attributes: attrParams,
    context: nil
)

In rare cases (for some UIFonts) it works ok, but for most of the other fonts toUseForDrawingBounds.height is almost always 1 blank line too big. (my input string text is always trimmed with whitespacesAndNewlines)

EDIT 2: After some testing I noticed this was not the case. With every UIFont (different combinations of font sizes & text) it can happen the returned height is 1 blank line too big. When I calculated number of lines (toUseForDrawingBounds.height / font.lineHeight) I clearly saw that sometimes returned number of lines was 1 too many.

I have tried tricks (StackOverflow) with (sizeToFit, etc.) UITextViews, UILabels, etc. Nothing really worked. Any ideas?

EDIT: To give a clear example, look at the attached image. Yellow rectangle approx. represents returned toUseForDrawingBounds bounds. I need proper bounds height so I can draw text vertically centered.

enter image description here

sabiland
  • 2,526
  • 1
  • 25
  • 24
  • Why are you using `NSString`? You should be using `String` with Swift. – Fogmeister Aug 01 '19 at 10:50
  • Yes ok, but would that make any difference? I'll try with String. – sabiland Aug 01 '19 at 10:51
  • The result is the same with String. – sabiland Aug 01 '19 at 11:05
  • @sabiland - I seem to get reliable results using the extension(s) found here https://stackoverflow.com/questions/30450434/figure-out-size-of-uilabel-based-on-string-in-swift ... you said *"In rare cases (for some UIFonts) it works ok, but for most of the other fonts"* --- can you list a couple specific Fonts that are giving you the incorrect heights? – DonMag Aug 01 '19 at 13:39
  • I'll do some tests today and list some Ok-working fonts and Not-working fonts. Will also check https://stackoverflow.com/questions/30450434/figure-out-size-of-uilabel-based-on-string-in-swift – sabiland Aug 02 '19 at 05:11
  • Hmm but already second answer is this: "For multiline text this answer is not working correctly. " As you see I need multiline calculation, because my width is limited and. And I've also tried with UILabel sizeToFit, but I get almost exactly same (wrong) height. – sabiland Aug 02 '19 at 05:15
  • @sabiland - are you trying to get the height so you can draw the text to an image? – DonMag Aug 02 '19 at 18:16
  • I am trying to get height so I can later vertically-center drawn text. Because before that I calculate approx. optimal font-size (for any random UIFont (fontName)) for the visible area. – sabiland Aug 05 '19 at 10:48

2 Answers2

1

You can simply use size(withAttributes:) on String to get its height and width, i.e.

let text = "This is the sample text."
let textSize = text.size(withAttributes: [.font: myRandomFont, .paragraphStyle: ps])
print(textSize)

The above code is just an example of how you can proceed. Add the attributes as per your requirement.

PGDev
  • 23,751
  • 6
  • 34
  • 88
0

Though I do not understand downvotes (because it is not trivial solution for any random font-name and random text combination), I have somehow managed to approx. solve my problem.

Just to summarize if anyone should have the same problems. I wanted to get an optimal font-size for randomly chosen font-name and randomly chosen input text to be drawn inside specified CGRect (so, wordWrapped).

I did this like this:

  1. For random font-name I took character "W" and with String.size(withAttributes:) and NSLineBreakMode.byWordWrapping I calculated maximum possible (binary search) fontSize to fit in CGRect
  2. Then I checked if fontSize > CGRect.height (yes it can happen!) and reduced fontSize to CGRect.height (actually this 2 step solved almost all of my issues)
  3. Then I just sqrt(pow(fontSize, 2) / numOfChars)) to get approx. optimal font-size to draw a text in a CGRect
sabiland
  • 2,526
  • 1
  • 25
  • 24