回答:
ほとんどの場合、Mattのソリューションは期待どおりに機能することに注意してください。それでもうまくいかない場合は、さらに読んでください。
ラベルの高さを自動的に変更するには、次の操作を行う必要があります。
例えば:
self.descriptionLabel = [[UILabel alloc] init];
self.descriptionLabel.numberOfLines = 0;
self.descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.descriptionLabel.preferredMaxLayoutWidth = 200;
[self.descriptionLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.descriptionLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.descriptionLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:self.descriptionLabel];
NSArray* constrs = [NSLayoutConstraint constraintsWithVisualFormat:@"|-8-[descriptionLabel_]-8-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)];
[self addConstraints:constrs];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-8-[descriptionLabel_]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)]];
[self.descriptionLabel addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[descriptionLabel_(220@300)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)]];
Interface Builderの使用
4つの制約を設定します。高さの制約は必須です。
次に、ラベルの属性インスペクターに移動して、行数を0に設定します。
ラベルのサイズインスペクターに移動し、垂直方向のContentHuggingPriorityと垂直方向のContentCompressionResistancePriorityを増やします。
高さの制約を選択して編集します。
また、高さ制約の優先度を下げます。
楽しい。:)
preferredMaxLayoutWidth
か、ラベルの幅(またはその右側と左側)を固定します。それで全部です!次に、コンテンツに合わせて垂直方向に自動的に拡大および縮小します。
iOS 6では、autolayoutを使用して、UILabelの側面(または幅)と上部が固定されている場合、コンテンツに合わせて自動的に垂直方向に拡大および縮小します。コードはまったくなく、圧縮抵抗などをいじる必要もありません。とても簡単です。
より複雑なケースでは、ラベルを設定するだけpreferredMaxLayoutWidth
です。
どちらにしても、正しいことが自動的に行われます。
label.sizeToFit()
質問はプログラムで述べられており、同じ問題が発生し、Interface Builderで作業することを望んでいますが、Interface Builderソリューションを使用して既存の回答に追加すると便利だと思いました。
最初のことは忘れることsizeToFit
です。自動レイアウトは、固有のコンテンツサイズに基づいてこれを処理します。
したがって、問題は、自動レイアウトを使用してラベルをそのコンテンツに合わせる方法を教えてください。具体的には-質問が言及しているため-高さ。同じ原則が幅にも適用されることに注意してください。
それでは、高さを41pxに設定したUILabelの例から始めましょう。
上の画面でわかる"This is my text"
ように、上下にパディングがあります。これは、UILabelの高さとそのコンテンツであるテキストの間のパディングです。
アプリをシミュレーターで実行すると、確かに同じことがわかります。
次に、Interface BuilderでUILabelを選択して、サイズインスペクターのデフォルト設定を見てみましょう。
上記の強調表示された制約に注意してください。それがコンテンツハグの優先事項です。Erica Sadunが優れたiOS Auto Layout Demystifiedで説明しているように、これは次のとおりです。
ビューがコアコンテンツの周りの余分なパディングを避けることを好む方法
私たちにとって、UILabelでは、コアコンテンツはテキストです。
ここで、この基本的なシナリオの中心に来ます。テキストラベルに2つの制約を与えました。彼らは対立します。ある人は、「高さは41ピクセルの高さに等しくなければならない」と言っています。もう1つは、「コンテンツのビューをハグして、余分なパディングがないようにする」です。私たちの場合、ビューをテキストにハグして、余分なパディングがないようにします。
さて、自動レイアウトでは、異なることを行う2つの異なる命令により、ランタイムはどちらか一方を選択する必要があります。両方はできません。UILabelを41ピクセルの高さにしたり、パディングを入れたりすることはできません。
これを解決する方法は、優先順位を指定することです。1つの命令は、他の命令よりも優先度が高くなければなりません。両方の命令が異なることを言い、優先順位が同じである場合、例外が発生します。
だからそれをやってみましょう。高さの制約の優先度は1000で、これは必須です。内容を抱き締める高さは250で、弱いです。高さ制約の優先度を249に下げるとどうなりますか?
これで魔法の始まりがわかります。シムで試してみましょう:
驚くばかり!コンテンツハグを達成しました。高さ優先度249がコンテンツハグ優先度250よりも低いためです。基本的に、「ここで指定する高さは、コンテンツをハグするために指定した高さよりも重要ではありません」と言っています。だから、コンテンツをハグして勝つ。
要点は、ラベルをテキストに合わせて取得するには、高さまたは幅の制約を指定するだけでよく、その軸のコンテンツハグの優先順位制約に関連してその優先順位を正しく設定します。
読者のための練習として、幅に相当することを行います!
ラベルのpreferredMaxLayoutWidthをラベルの幅と同期させるための別のオプション:
#import "MyLabel.h"
@implementation MyLabel
-(void)setBounds:(CGRect)bounds
{
[super setBounds:bounds];
// This appears to be needed for iOS 6 which doesn't seem to keep
// label preferredMaxLayoutWidth in sync with its width, which
// means the label won't grow vertically to encompass its text if
// the label's width constraint changes.
self.preferredMaxLayoutWidth = self.bounds.size.width;
}
@end
適切な解決策を見つけるのにしばらく時間がかかったので、私は貢献すべきだと思います。
基本的に何が起こるかというと、UILabelに固定高さの制約があっても、コンテンツをハグするために制約を解除してそれ自体を小さくできる(たとえば、1行の場合)が、それができないことです。制約を解除して大きくします。
私の場合、UILabel(長さが不明)を含むUIViewサブクラスを作成していました。iOS7では、コードは簡単でした。制約を設定し、コンテンツのハグや圧縮の耐性について心配しないでください。すべてが期待どおりに機能しました。
しかしiOS6では、UILabelは常に1行にクリップされていました。上記の答えはどれもうまくいきませんでした。コンテンツハグと圧縮耐性の設定は無視されました。クリッピングを防ぐ唯一の解決策は、ラベルにpreferredMaxLayoutWidthを含めることでした。しかし、親ビューのサイズが不明だったため、適切な幅を何に設定するかわかりませんでした(実際、内容によって定義されます)。
私は最終的にここで解決策を見つけました。私はカスタムビューで作業していたため、次のメソッドを追加して、制約が1回計算された後に優先レイアウト幅を設定し、それらを再計算することができます。
- (void)layoutSubviews
{
// Autolayout hack required for iOS6
[super layoutSubviews];
self.bodyLabel.preferredMaxLayoutWidth = self.bodyLabel.frame.size.width;
[super layoutSubviews];
}
UIFont *customFont = myLabel.font;
CGSize size = [trackerStr sizeWithFont:customFont
constrainedToSize:myLabel.frame.size // the size here should be the maximum size you want give to the label
lineBreakMode:UILineBreakModeWordWrap];
float numberOfLines = size.height / customFont.lineHeight;
myLabel.numberOfLines = numberOfLines;
myLabel.frame = CGRectMake(258, 18, 224, (numberOfLines * customFont.lineHeight));
この問題に遭遇したのは、UILabelが内部要素の場合と同じように含まれているUIViewサブクラスでした。自動レイアウトを使用して、推奨されるすべての解決策を試しても、ラベルはテキストに合わせて高さを調整しませんでした。私の場合、ラベルを1行にするだけです。
とにかく、私にとってうまくいったことは、UILabelに必要な高さの制約を追加し、intrinsicContentSizeが呼び出されたときに手動で正しい高さに設定することでした。UILabelが別のUIViewに含まれていない場合は、UILabelをサブクラス化して、最初に高さの制約を設定してから
[super instrinsicContentSize]を返すことで同様の実装を提供できます。[self.containerview組み込みeContentSize]の代わりに; 以下のように、これは私のUIViewサブラスに固有のものです。
- (CGSize)intrinsicContentSize
{
CGRect expectedTextBounds = [self.titleLabel textRectForBounds:self.titleLabel.bounds limitedToNumberOfLines:1];
self.titleLabelHeightConstraint.constant = expectedTextBounds.size.height;
return [self.containerView intrinsicContentSize];
}
iOS 7およびiOS 8で完全に動作します。
intrinsicContentSize
。ランタイムは、正しく設定された制約に基づいてこれを計算できるはずです。
私の場合、UITableViewCellでラベルを使用すると、ラベルのサイズは変更されますが、高さがテーブルのセルの高さを超えてしまいます。これは私のために働いたものです。Max MacLeodによると、セルの高さがUITableViewAutomaticDimensionに設定されていることを確認しました。
これをinitまたはawakeFromNibに追加できます。
self.tableView.rowHeight = UITableViewAutomaticDimension.
ストーリーボードでセルを選択し、サイズインスペクタを開いて、[カスタム]チェックボックスをオフにして、行の高さが「デフォルト」に設定されていることを確認します。
8.0にも問題があり、コードで設定する必要があります。
label.sizeToFit()
Xcode / viewControllerで使用する必要はありませんでした。制約は十分でした。Playgroundでラベルを作成していませんでした。これまでのところ、プレイグラウンドで動作するように私が見つけた唯一の方法は、実行することですlabel.sizeToFit()