高さがテキストに依存するUILabelをプログラムで(およびどの方法で)構成するのですか?私はストーリーボードとコードの組み合わせを使用してセットアップしようとしましたが、役に立ちませんでした。 sizeToFit
およびlineBreakMode
を設定する際は、numberOfLines
をお勧めします。ただし、そのコードをviewDidLoad:
、viewDidAppear:
、またはviewDidLayoutSubviews
に配置しても、動作させることはできません。長いテキストに対してボックスを小さくしすぎてサイズが大きくならないか、大きすぎてサイズが小さくなりません。
注意してくださいほとんどの場合 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を増やします。
高さの制約を選択して編集します。
そして、高さの制約の優先順位を下げます。
お楽しみください。 :)
IOS 6では、自動レイアウトを使用して、UILabelの側面(または幅)と上部が固定されている場合、自動内容に合わせて垂直方向に拡大および縮小しますコードなし =そして、その圧縮抵抗または何でも混乱しません。まったく簡単です。
より複雑な場合は、ラベルのpreferredMaxLayoutWidth
を設定するだけです。
どちらにしても、正しいことが自動的に行われます。
質問はプログラムで述べており、同じ問題に遭遇し、Interface Builderでの作業を希望していますが、Interface Builderソリューションを使用して既存の回答に追加することが役立つかもしれません。
最初のことは、sizeToFit
を忘れることです。自動レイアウトは、固有のコンテンツサイズに基づいてユーザーに代わってこれを処理します。
したがって、問題は、自動レイアウトでコンテンツに合わせてラベルを取得する方法ですか?具体的には-質問がそれに言及しているため-高さ。同じ原則が幅にも適用されることに注意してください。
41pxの高さに設定されたUILabelの例から始めましょう。
上記のスクリーングラブでわかるように、"This is my text"
には上下にパディングがあります。これは、UILabelの高さとコンテンツ、つまりテキストの間のパディングです。
シミュレータでアプリを実行すると、確かに同じことがわかります。
次に、Interface BuilderでUILabelを選択し、サイズインスペクターのデフォルト設定を見てみましょう。
上記の強調表示された制約に注意してください。それがContent Hugging Priorityです。 Erica Sadunが優れた iOS Auto Layout Demystified で説明しているように、これは次のとおりです。
ビューがコアコンテンツの周りに余分なパディングを避けることを好む方法
私たちにとって、UILabelのコアコンテンツはテキストです。
ここで、この基本的なシナリオの中心に来ます。テキストラベルに2つの制約を与えました。彼らは対立します。 「高さは41ピクセルの高さに等しくなければならない」と言います。もう1つは、「ビューをコンテンツに合わせて余分なパディングがないようにする」と言います。私たちの場合、ビューを text にハグするので、余計なパディングはありません。
さて、自動レイアウトでは、異なることを行うという2つの異なる命令により、ランタイムはどちらかを選択する必要があります。両方を行うことはできません。 UILabelの高さを41ピクセルにすることはできません。 and にはパディングがありません。
これを解決する方法は、優先度を指定することです。 1つの命令には、他の命令よりも高い優先度が必要です。両方の命令が異なることを言い、同じ優先度を持っている場合、例外が発生します。
それでは、試してみましょう。私の身長制限の優先順位は10、つまりrequiredです。コンテンツのハグの高さは25、つまりweakです。高さ制約の優先順位を249に下げるとどうなりますか?
これで、魔法が始まります。シムで試してみましょう:
驚くばかり!コンテンツのハグが達成されました。高さの優先順位249がコンテンツのハグの優先順位25よりも小さいためです。基本的に、「ここで指定する高さは、コンテンツのハグに指定した高さよりも重要度が低い」と言います。だから、コンテンツのハグが勝つ。
下線、テキストに合わせてラベルを取得することは、高さまたは幅の制約を指定するのと同じくらい簡単で、その軸のコンテンツの優先度制約に関連してその優先度を正しく設定できます。
読者のための練習として、幅に相当することをしておきます!
IOS7で気づいたsizeToFitも機能していません-おそらく解決策もあなたを助けるかもしれません
[textView sizeToFit];
[textView layoutIfNeeded];
適切な解決策を見つけるのに少し時間がかかったので、貢献すべきだと感じています
基本的に、UILabelに固定の高さの制約がありますが、コンテンツをハグするために制約を解除して小さくすることができます(たとえば、1行の場合)制約を解除して大きくします。
ラベルの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(長さ不明)を含むUIViewサブクラスを作成していました。 iOS7では、コードは簡単でした。制約を設定し、コンテンツのハグや圧縮抵抗を心配せず、すべてが期待どおりに機能しました。
しかし、iOS6では、UILabelは常に1行にクリップされていました。上記の答えはどれも私にとってはうまくいきませんでした。コンテンツのハグと圧縮抵抗の設定は無視されました。クリッピングを防ぐ唯一の解決策は、ラベルにpreferredMaxLayoutWidthを含めることでした。しかし、親ビューのサイズが不明であるため、優先幅をどのように設定するかわかりませんでした(実際、コンテンツによって定義されます)。
私は最終的に解決策を見つけました ここ 。カスタムビューで作業していたので、次のメソッドを追加するだけで、制約が一度計算された後に優先レイアウト幅を設定し、再計算できます。
- (void)layoutSubviews
{
// Autolayout hack required for iOS6
[super layoutSubviews];
self.bodyLabel.preferredMaxLayoutWidth = self.bodyLabel.frame.size.width;
[super layoutSubviews];
}
プログラムでUILabel
を追加しましたが、私の場合はこれで十分です。
label.translatesAutoresizingMaskIntoConstraints = false
label.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: .Vertical)
label.numberOfLines = 0
「優先幅」を「自動」に設定し、ラベルの先頭、先頭、末尾を固定するxCode6で解決しました
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を1つとして含むUIViewサブクラスでもこの問題に遭遇しました。自動レイアウトを使用し、推奨されるすべての解決策を試しても、ラベルの高さはテキストに対して厳しくなりません。私の場合、ラベルを1行にしたいだけです。
とにかく、私のために働いたのは、UILabelに必要な高さの制約を追加し、intrinsicContentSizeが呼び出されたときに正しい高さに手動で設定することでした。別のUIViewにUILabelが含まれていない場合は、UILabelをサブクラス化して、最初に高さの制約を設定してから返すことにより、同様の実装を提供できます
[super instrinsicContentSize]; [self.containerviewintrinsiceContentSize];の代わりに私の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で完全に動作するようになりました。