3
votes

I have NSTextField with left, right and top constraints defined (no bottom constraint set). I need NSTextField to grow if content can't fit in it and decrease size if there is unused space left.

Now I have: NSTextField automatically expands with strange behavior if it has multi-line text or too much content, also NSTextField doesn't decrease own's size on window resize.

I haven't found any simple solution written on Swift to solve that problem (I have a lot of such labels with constraints), at iOS everything was working with usual text labels and constraints.

Illustration

I've created simple project for that question that you can see the problem: [Download Text.zip]

The solutions I've found but not used:

  1. You can try to calculate possible TextField height and set height constraint for it. Problems of that solution:

    • Possible height calculations are inaccurate, sometimes you calculate incorrect height.
    • Solutions are written on Objective-C with some complex code.
  2. Run .sizeToFit() on each window resize or text change action. It's not working because .sizeToFit() always compress all text to single line.

  3. Use NSTextView instead of NSTextField. It's good way, but:

    • I don't need scrolling, editing and other functional of NSTextView. I don't want to call to complex component for simple label.
    • NSTextView always wants height or bottom constraint, I don't know bottom constraint because content can expand down with new text.
    • I haven't find full solution to make NSTextView's behavior like I want :)
1
Disable first runtime layout width and play with this textField.needsLayout = true textField.needsUpdateConstraints = true textField.needsDisplay = true. I do not know how to force refresh the view other then NSWindow live resizing. So once you call addText the view does not expand. But it will correctly redraw on window resize.Marek H
@xhruso00, if I disable first runtime layout NSTextField is always displayed as 1 line. needsLayout, needsUpdateConstraints, needsDisplay has no effect at all (on my tests).Vasily
Have you resized window after clicking on button? Only then the view refreshes. If you solve the redraw it will behave as you want with almost no code.Marek H
@xhruso00, I've added code on addText action, nothing works with resizing windows or without. You can check XCode's sample here: dl.dropboxusercontent.com/u/42855950/Text2.zipVasily
You are right. I commented the code i recommended and the resizing is default behaviour on El Cap. You have to check AppKit internals what they do or wait. onlinevideoconverter.com/…Marek H

1 Answers

3
votes

According to Mac OS X Release Notes (section NSTextField intrinsicContentSize improvements) it’s known bug when height of NSTextField is changed, but width is remained the same. We have two ways to fixing it:

  1. We can specify maximumNumberOfLines to a value that makes sense. That is not good way to us because we don’t know actual number of lines and don’t want to calculate it.
  2. We can set preferredMaxLayoutWidth to a real value. I’ve ended with such code:

Code:

override func viewDidLayout() {
    super.viewDidLayout()
    textField.preferredMaxLayoutWidth = textField.frame.width
}