iOS:自動レイアウトの複数行のUILabel


183

自動レイアウトで非常に基本的なレイアウト動作を実現しようとして問題が発生しています。私のビューコントローラーはIBでは次のようになります。

ここに画像の説明を入力してください

トップラベルはタイトルラベルですが、行数はわかりません。テキストのすべての行を表示するには、タイトルラベルが必要です。また、他の2つのラベルと小さな画像をタイトルのすぐ下に配置する必要があります。ラベルと小さな画像の間の垂直方向の間隔の制約、およびタイトルラベルとそのスーパービューの間の上部の間隔の制約、および小さな画像とそのスーパービューの間の下部の間隔の制約を設定しました。白いUIViewには高さの制約がないため、サブビューを含めるには垂直方向に引き伸ばす必要があります。タイトルラベルの行数を0に設定しました。

文字列に必要な行数に合わせてタイトルラベルのサイズを変更するにはどうすればよいですか?私の理解では、自動レイアウトを使用しているため、setFrameメソッドを使用できません。そして、他のビューがタイトルラベルの下に留まるようにする必要があるため(これにより制約があるため)、自動レイアウトを使用する必要があります。

どうすればこれを実現できますか?


3
私も同様の問題で戦っています。しかし、私はまだトップラベルがコンテンツに合わせて高さを動的に調整するのに苦労しています。どのようにしてこれを達成しましたか?
jbandi

1
@mwhussの回答を承認済みとしてマークすることを検討してください。
jemmons 2014

1
必要な結果を達成しましたか?
Aniruddha 2014

これを確認してください。1
a/36862795/

回答:


254

とautolayoutでの使用-setPreferredMaxLayoutWidthは、UILabel残りを処理する必要があります。

[label setPreferredMaxLayoutWidth:200.0];

preferredMaxLayoutWidthのUILabelドキュメントを参照してください。

更新:

heightストーリーボードの制約をに設定するだけでGreater than or equal to、setPreferredMaxLayoutWidth を設定する必要はありません。


8
いいですね、とにかくこれをインターフェースビルダーで行うには?
Sjoerd Perfors 2013

12
また、より大きいにIBにおける高さの制約を設定するか「に等しい。
jowieを

10
注意:numberOfLinesプロパティを設定することを忘れないでください。
Li Fumin、2015

2
うん、最大幅にしたいものを使いなさい。
mwhuss、2015年

4
devetc.org/code/2014/07/07/auto-layout-and-views-that-wrap.htmlを確認して確認する方法については、stackoverflow.com / a / 29180323/1529675preferredMaxLayoutWidth参照してください。アニメーションGIF(私の記事ではなく、Googleで見つけました)
tboyce12 '9/10/15

213

ラベルセットの行数を0に拡張し、自動レイアウトセットの高さを> = xに拡張します。残りは自動レイアウトが行います。正しく配置するために、前の要素に基づく他の要素を含めることもできます。

自動レイアウト


この方法がうまくいかない場合は、自動レイアウトが(おそらく)複数行のビューのサイズを変更することを後続のビューが禁止しないようにすることについて、Cory Imdiekeの回答を参照してください。
トムハワード

1
これは、テーブルビューセル内で私のために働いた唯一の答えです。(0 /無制限ではなく)固定数の行でも機能します
bgolson '19年

これは、明示的に推奨される最大幅を設定した場合には機能しなかったため、この手法を使用する場合は、IBでこれが自動に設定されていることを確認してください。乾杯
jmc 2015

自動最大幅の設定は、iOS8でのみ使用できます。また、私の理解では、高さを自動的に調整します。私の経験では、高さの制約を設定する必要はありません。これは、明示的な幅を使用して私にとってうまくいきました。
Tony

1
これは私にはうまくいきませんでした。stackoverflow.com/a/13032251/1529675が正しい答えだと思います。
tboyce12

48

出典:http : //www.objc.io/issue-3/advanced-auto-layout-toolbox.html

複数行テキストの固有のコンテンツサイズ

UILabelとNSTextFieldの固有のコンテンツサイズは、複数行のテキストではあいまいです。テキストの高さは線の幅に依存しますが、これは制約を解決するときにまだ決定されていません。この問題を解決するために、どちらのクラスにも、preferredMaxLayoutWidthという新しいプロパティがあり、固有のコンテンツサイズを計算するための最大線幅を指定します。

通常、この値は事前にわからないため、これを正しく行うには2段階のアプローチをとる必要があります。最初に自動レイアウトを機能させ、次に、結果のフレームをレイアウトパスで使用して、推奨される最大幅を更新し、レイアウトを再度トリガーします。

- (void)layoutSubviews
{
    [super layoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [super layoutSubviews];
}

[super layoutSubviews]への最初の呼び出しは、ラベルがフレームセットを取得するために必要ですが、2番目の呼び出しは変更後にレイアウトを更新するために必要です。2番目の呼び出しを省略すると、NSInternalInconsistencyExceptionエラーが発生します。これは、制約の更新を必要とするレイアウトパスに変更を加えたため、レイアウトを再度トリガーしなかったためです。

これをラベルサブクラス自体で行うこともできます。

@implementation MyLabel
- (void)layoutSubviews
{
    self.preferredMaxLayoutWidth = self.frame.size.width;
    [super layoutSubviews];
}
@end

この場合、最初に[super layoutSubviews]を呼び出す必要はありません。これは、layoutSubviewsが呼び出されたときに、ラベル自体に既にフレームがあるためです。

ビューコントローラーレベルからこの調整を行うには、viewDidLayoutSubviewsにフックします。この時点で、最初の自動レイアウトパスのフレームはすでに設定されているので、それらを使用して適切な最大幅を設定できます。

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [self.view layoutIfNeeded];
}

最後に、ラベルのコンテンツ圧縮耐性の優先度よりも高い優先度を持つ、ラベルに明示的な高さ制限がないことを確認してください。それ以外の場合は、コンテンツの計算された高さよりも優先されます。ラベルの高さに影響を与える可能性のあるすべての制約を確認してください。


コードだけでなく、サブクラスだけでなく、View Controllerからこれを行う方法の説明と例についても感謝します。
djibouti33 2015

私はビューコントローラーでこれを試みており、viewWillAppearおよびviewDidAppearの後にviewDidLayoutSubviewsが呼び出されています。viewDidAppearの後、ラベルが正しくサイズ変更されるとフラッシュが発生します。これを回避する方法はありますか?ユーザーが何かを見る前にサイズ変更を完了する方法はありますか?私の場合、私のマルチラインラベルはtableHeaderViewであり、そしてIはまた、この例(使用したラベルに基づいてヘッダビューの高さをリサイズしていてstackoverflow.com/questions/20982558/...を
djibouti33

@ djibouti33問題を簡単に確認できるように、最小限のサンプルコード(たとえばgithub repoの形式)を提供できますか?
アントンマトソフ

@Antonに感謝します。その後、デザインはUITableViewからUICollectionViewに切り替わりました。幸い、この動作は見られませんでした。gitの履歴で小さなサンプルプロジェクトを作成できる場合は、お知らせします。
ジブチ33

iOS 9のsimで実行を開始してからの問題ですが、iOS 8でテストすると問題が発生しました。最大幅を手動で設定する必要があります。
naz 2015年

17

私はこの正確なシナリオで戦っていましたが、必要に応じてサイズを変更し、下に移動する必要があるかなり多くのビューがありました。気が動転しましたが、ようやくわかりました。

重要な点は次のとおりです。インターフェイスビルダーは、ビューを追加したり移動したりするときに余分な制約を課すことを好み、気付かない場合があります。私の場合、半分下のビューに、そのビューとスーパービューの間のサイズを指定する追加の制約があり、基本的にはそのポイントに固定されていました。つまり、その制約に反するため、それ以上のサイズに変更することはできません。

これに該当するかどうかを確認する簡単な方法は、手動でラベルのサイズを変更することです。IBで成長させることができますか?その場合、下のラベルは期待どおりに移動しますか?サイズを変更する前にこれらの両方がチェックされていることを確認して、制約によってビューがどのように移動するかを確認してください。

IBメニュー

ビューがスタックしている場合は、その下にあるビューをたどり、ビューの1つに上部ビューの制約がないことを確認してください。次に、ラベルの行数オプションが0に設定されていることを確認するだけで、残りの部分が処理されます。


うん、たくさん遊んでみたところ、思い通りの効果が得られました。必要な制約について非常に注意深く考える必要があります。IBが予期しない制約を絶えず投入していることは役に立ちません。
James Harpe、

5

次のものが必要です。

  • 上位の制約
  • 先行制約(例:左側)
  • 末尾の制約(例:右側)
  • コンテンツのハグの優先度を水平から低に設定します。これにより、テキストが短い場合は指定されたスペースが埋められます。
  • コンテンツの圧縮抵抗を水平から低に設定すると、幅を広くしようとせずに折り返されます。
  • 行数を0に設定します。
  • 改行モードをワードラップに設定します。

これはxcode9で動作するはずです。ラベルの高さの制約については何もする必要がありませんでした(私は何もしていません)。ラベルが制約された(後部、前部、上部、下部)と、箱から出してすぐに機能します。uikitが残りの作業を行う
アントントロパシュコ2017

優先順位を抱いているコンテンツが私の問題でした。その特性と耐圧縮性を知っていただきありがとうございます。あなたは私が1時間にわたる問題を解決するのを助けました。
デビッドゲイ

0

この件に関する多くのトピックで見つかったさまざまな解決策はどれも、私の場合には完全に機能しませんでした(動的テーブルビューセルのx動的複数行ラベル)。

私はそれをする方法を見つけました:

ラベルに制約を設定し、そのmultilineプロパティを0に設定した後、UILabelのサブクラスを作成します。私は私をAutoLayoutLabelと呼びました:

@implementation AutoLayoutLabel

- (void)layoutSubviews{
    [self setNeedsUpdateConstraints];
    [super layoutSubviews];
    self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
}

@end

0

テキストラップラベルのあるUITableViewCellがあります。テキストの折り返しは次のように行いました。

1)UILabel制約を次のように設定します。

ここに画像の説明を入力してください

2)セット番号 行の0に。

3)UILabelの高さ制約をUITableViewCellに追加しました。

@IBOutlet weak var priorityLabelWidth: NSLayoutConstraint!

4)UITableViewCell:

priorityLabel.sizeToFit()
priorityLabelWidth.constant = priorityLabel.intrinsicContentSize().width+5

-12

これを行う1つの方法...テキストの長さが増加するにつれて、次を使用してラベルテキストのフォントサイズを変更(減少)してみます。

Label.adjustsFontSizeToFitWidth = YES;

1
ビューコントローラーのさまざまなインスタンスに一貫した外観を持たせたいので、フォントサイズを変更したくありません。
James Harpe、2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.