Auto Layout で幅に応じて Label(NSTextField)を折り返す
- Apple
- 開発
AppKit で Label といえば、NSLabel
...ではなく NSTextField
を使う。それを Auto Layout 1で扱うのが今日のテーマだ。
単純に配置するだけなら何も考えなくていいけど、必要な幅が長くなったら下の GIF アニメーションのように折り返したい。
こうやって上下左右に Constraint を追加しただけの単純なウインドウで考えてみよう:
Interface Builder だけでできるよ!
調べるとサブクラスを作って layout()
のタイミングで preferredMaxLayoutWidth
を指定するみたいな大掛かりな話ばかり。
そんなはずはないと思って Interface Builder で Line Break を Word Wrap にして水平方向の Content Compression Resistance Priority を下げただけでできた。それが冒頭の GIF アニメーションの状態だ。なんだ、簡単じゃん。
いつから使える...?
気になるのはどのバージョンから対応しているかだ。昔はできなかった気がして試しに上で作ったサンプル App を VMware 上の Yosemite で動かしてみたらまったくダメだった。改行なんてしてくれない。いつからできるようになったのだろうか。
こういうときに頼りになるのが NSTextField
のリファレンス...ではなく、例によって AppKit Release Notes だ。検索すると、まさにこの変更の記載「NSTextField intrinsicContentSize improvements」が OS X 10.11 のところにあった。
Previously, unless NSTextField’s preferredMaxLayoutWidth was set to something other than 0, the -intrinsicContentSize method would measure the text field with its contents on a single line, even if wrapping was enabled. Because of this behavior, the auto layout engine would not be able to find a size for a text field that spanned multiple lines, even though doing so would produce an acceptable and aesthetically better layout.
We’ve changed things such that the autolayout engine provides a width that acts like the preferredMaxLayoutWidth for the NSTextField, allowing for a text field to reflow into multiple lines. This works only for apps linked against 10.11 that have wrapping text and a preferredMaxLayoutWidth of 0. Also, it only works if the constraints on the text field allow for content compression.
preferredMaxLayoutWidth
を与えなくても適当に判断してくれるらしい。このほか Attributed String を使った場合の注意点なども書いてる。preferredMaxLayoutWidth
の挙動にも関わってくるようで、Label を Auto Layout で並べたい人は目を通しておくとよさそうだ2。
2020.11.2 追記
気になって UIKit の世界も調べてみたら
Automatic Preferred Max Layout Width is not available on iOS versions prior to 8.0
ということらしい。
Yosemite はまだ切れないことが多いけどさすがに iOS 8 はサポートしなくてもよさそうなので、Auto Layout なのに UILabel.preferredMaxLayoutWidth
を手動で指定しているコードを見つけたらほとんどが取り除けるかも。
Share
リンクも共有もお気軽に。記事を書くモチベーションの向上に役立てます。