web-dev-qa-db-ja.com

UILabel sizeToFitは自動レイアウトios6では機能しません

高さがテキストに依存するUILabelをプログラムで(およびどの方法で)構成するのですか?私はストーリーボードとコードの組み合わせを使用してセットアップしようとしましたが、役に立ちませんでした。 sizeToFitおよびlineBreakModeを設定する際は、numberOfLinesをお勧めします。ただし、そのコードをviewDidLoad:viewDidAppear:、またはviewDidLayoutSubviewsに配置しても、動作させることはできません。長いテキストに対してボックスを小さくしすぎてサイズが大きくならないか、大きすぎてサイズが小さくなりません。

151
circuitlego

注意してくださいほとんどの場合 Mattの解 は期待どおりに動作します。しかし、それがうまくいかない場合は、さらに読んでください。

ラベルの高さを自動的に変更するには、以下を実行する必要があります。

  1. ラベルのレイアウト制約を設定する
  2. 低優先度で高さの制約を設定します。 ContentCompressionResistancePriorityよりも低くする必要があります
  3. NumberOfLines = 0を設定します
  4. ContentHuggingPriorityをラベルの高さ優先度よりも高く設定します
  5. ラベルのpreferredMaxLayoutWidthを設定します。その値は、ラベルによってその高さを計算するために使用されます

例えば:

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の使用

  1. 4つの制約を設定します。高さの制約は必須です。 enter image description here

  2. 次に、ラベルの属性インスペクターに移動し、行数を0に設定します。 enter image description here

  3. ラベルのサイズインスペクターに移動し、垂直ContentHuggingPriorityおよび垂直ContentCompressionResistancePriorityを増やします。
    enter image description here

  4. 高さの制約を選択して編集します。
    enter image description here

  5. そして、高さの制約の優先順位を下げます。
    enter image description here

お楽しみください。 :)

404

IOS 6では、自動レイアウトを使用して、UILabelの側面(または幅)と上部が固定されている場合、自動内容に合わせて垂直方向に拡大および縮小しますコードなし =そして、その圧縮抵抗または何でも混乱しません。まったく簡単です。

より複雑な場合は、ラベルのpreferredMaxLayoutWidthを設定するだけです。

どちらにしても、正しいことが自動的に行われます。

64
matt

質問はプログラムで述べており、同じ問題に遭遇し、Interface Builderでの作業を希望していますが、Interface Builderソリューションを使用して既存の回答に追加することが役立つかもしれません。

最初のことは、sizeToFitを忘れることです。自動レイアウトは、固有のコンテンツサイズに基づいてユーザーに代わってこれを処理します。

したがって、問題は、自動レイアウトでコンテンツに合わせてラベルを取得する方法ですか?具体的には-質問がそれに言及しているため-高さ。同じ原則が幅にも適用されることに注意してください。

41pxの高さに設定されたUILabelの例から始めましょう。

enter image description here

上記のスクリーングラブでわかるように、"This is my text"には上下にパディングがあります。これは、UILabelの高さとコンテンツ、つまりテキストの間のパディングです。

シミュレータでアプリを実行すると、確かに同じことがわかります。

enter image description here

次に、Interface BuilderでUILabelを選択し、サイズインスペクターのデフォルト設定を見てみましょう。

enter image description here

上記の強調表示された制約に注意してください。それがContent Hugging Priorityです。 Erica Sadunが優れた iOS Auto Layout Demystified で説明しているように、これは次のとおりです。

ビューがコアコンテンツの周りに余分なパディングを避けることを好む方法

私たちにとって、UILabelのコアコンテンツはテキストです。

ここで、この基本的なシナリオの中心に来ます。テキストラベルに2つの制約を与えました。彼らは対立します。 「高さは41ピクセルの高さに等しくなければならない」と言います。もう1つは、「ビューをコンテンツに合わせて余分なパディングがないようにする」と言います。私たちの場合、ビューを text にハグするので、余計なパディングはありません。

さて、自動レイアウトでは、異なることを行うという2つの異なる命令により、ランタイムはどちらかを選択する必要があります。両方を行うことはできません。 UILabelの高さを41ピクセルにすることはできません。 and にはパディングがありません。

これを解決する方法は、優先度を指定することです。 1つの命令には、他の命令よりも高い優先度が必要です。両方の命令が異なることを言い、同じ優先度を持っている場合、例外が発生します。

それでは、試してみましょう。私の身長制限の優先順位は10、つまりrequiredです。コンテンツのハグの高さは25、つまりweakです。高さ制約の優先順位を249に下げるとどうなりますか?

enter image description here

これで、魔法が始まります。シムで試してみましょう:

enter image description here

驚くばかり!コンテンツのハグが達成されました。高さの優先順位249がコンテンツのハグの優先順位25よりも小さいためです。基本的に、「ここで指定する高さは、コンテンツのハグに指定した高さよりも重要度が低い」と言います。だから、コンテンツのハグが勝つ。

下線、テキストに合わせてラベルを取得することは、高さまたは幅の制約を指定するのと同じくらい簡単で、その軸のコンテンツの優先度制約に関連してその優先度を正しく設定できます。

読者のための練習として、幅に相当することをしておきます!

42
Max MacLeod

IOS7で気づいたsizeToFitも機能していません-おそらく解決策もあなたを助けるかもしれません

[textView sizeToFit];
[textView layoutIfNeeded];
7
Nick Wood

適切な解決策を見つけるのに少し時間がかかったので、貢献すべきだと感じています

  • 目標は、sizeToFit()を呼び出さずに自動レイアウトが機能するようにすることです。適切な制約を指定してこれを行います。
  • UILabelの上部、下部、および先頭/末尾スペースの制約を指定します
  • 行数プロパティを0に設定します
  • コンテンツハグの優先度を1000に増やす
  • コンテンツの圧縮抵抗の優先度を500に下げる
  • 下部のコンテナ制約で、優先度を500に下げます

基本的に、UILabelに固定の高さの制約がありますが、コンテンツをハグするために制約を解除して小さくすることができます(たとえば、1行の場合)制約を解除して大きくします。

4
ArturT

ラベルの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
4
Monte Hurd

私の場合、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];
}
3
sumizome

プログラムでUILabelを追加しましたが、私の場合はこれで十分です。

label.translatesAutoresizingMaskIntoConstraints = false
label.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: .Vertical)
label.numberOfLines = 0
2
mixel

「優先幅」を「自動」に設定し、ラベルの先頭、先頭、末尾を固定するxCode6で解決しました enter image description here

2
Kazzar
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));
0
Swati

私のために働いたソリューション。 UILabelの幅が固定されている場合、インターフェイスファイルで制約をconstant =からconstant <=に変更します

enter image description here

0
Alex Brown

内部要素の場合は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で完全に動作するようになりました。

0
n8tr