web-dev-qa-db-ja.com

サブビューが自動レイアウトを使用して動的に変更された後、スーパービューのサイズを変更します

神の愛のために、このサイズ変更スーパービューのこつはできません。

UIView *superviewに4つのUILabelsがあります。 2は他の2つのヘッダーとして機能します。

4つすべてのコンテンツは、データベースからの動的なものです。

SizeToFit vs SizeThatFits:(CGSize) vs UIView systemLayoutSizeFittingSize:UILayoutFittingCompressedSizeまたはUILayoutFittingExpandedSizeのいずれかを渡します。

プログラムで自動レイアウトを使用し、スーパービューの高さをダミーの数値以上に設定しました。

これらのSizeToFit vs sizeThatFits:(CGSize) vs UIView systemLayoutSizeFittingSize:をどこでどのように使用し、UILayoutFittingCompressedSizeまたはUILayoutFittingExpandedSizeを渡します。ここでスタックに関する多くのヒントを読みましたが、結局何もありませんでした。

スーパービューの制約を特定の場所で再計算する必要がありますか。 Mabyはコントローラークラスで高さを「@property」に設定し、それを削除して読み取りましたか? Atmすべての場所に配置してから、いくつか配置しようとしました。それでも、ダミーの高さとテキストが外側に浮かんだ同じサイズの最終結果が得られます。サブビューでclipsToBoundを設定した後でも。

私は髪を掻いています。

81
Pedroinpeace

自動レイアウトを使用している場合は、次のことを行う必要があります。

  1. サブビューに固定幅や高さの制約を追加していないことを確認してください(動的にサイズを決定するディメンションに応じて)。考え方は、各サブビューの固有のコンテンツサイズにサブビューの高さを決定させることです。 UILabelsには、(必要な優先度よりも低い)ラベルのフレームを、すべてのテキストを収めるために必要な正確なサイズに維持しようとする4つの自動暗黙制約が付属しています。

  2. 各ラベルの端が、必要な優先順位の制約を使用して、互いの端とスーパービューにしっかりと接続されていることを確認してください。ラベルの1つが大きくなることを想像した場合、他のラベルにスペースを空けさせ、最も重要なことにはスーパービューも同様に拡大させます。

  3. スーパービューに制約を追加するだけで、サイズではなく位置を設定できます(少なくとも、動的にサイズを調整したいディメンションでは)。内部制約を正しく設定すると、そのサイズはすべてのサブビューのサイズによって決定されることに注意してください。エッジは何らかの方法でそれらに接続されているためです。

それでおしまい。これを機能させるためにsizeToFitsystemLayoutSizeFittingSize:を呼び出す必要はありません。ビューをロードしてテキストを設定するだけです。システムレイアウトエンジンは、制約を解決するための計算を行います。 (もしあれば、スーパービューでsetNeedsLayoutを呼び出す必要があるかもしれませんが、これは必須ではありません。)

102
smileyborg

コンテナビューを使用する

次の例では、30x30の画像があり、UILabelはプレースホルダーテキストを含むビューよりも小さくなっています。収容ビューは少なくとも画像と同じ大きさである必要がありましたが、複数行のテキストを収容するには拡大する必要がありました。

視覚的な形式では、内部コンテナは次のようになります。

H:|-(15.0)-[image(30.0)]-(15.0)-[label]-(15.0)-|
V:|[image(30.0)]|
V:|[label(>=30.0)]|

次に、ラベルの高さと一致するように包含ビューを設定します。これで、包含ビューはラベルのサイズになります。

@smileyborgが彼の答えで指摘したように、コンテンツをスーパービューに厳密に接続すると、単純なコンテナビューによってコンテンツが成長するはずであることがレイアウトエンジンに通知されます。

黄色の整列長方形

黄色の整列長方形が必要な場合は、スキームの実行引数のリストに-UIViewShowAlignmentRects YESを追加します。

UILabel that is multi-line

24

これは、iOS 9のスタックビューの導入により劇的に簡単になりました。ビュー内でスタックビューを使用して、サイズ変更するすべてのコンテンツを含めてから、単に呼び出します。

view.setNeedsUpdateConstraints()
view.updateConstraintsIfNeeded()
view.setNeedsLayout()
view.layoutIfNeeded()

コンテンツを変更した後。次に、呼び出して新しいサイズを取得できます

view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

ビューに必要な正確なサイズを計算する必要がある場合。

5
Jacob Ruth

これは、@ smileyborgの回答にほぼ続き、具体的な例が付属しています。

enter image description here

すべての制約については説明しませんが、UIオブジェクトの高さの計算に関連する制約について説明します。

  1. [Label]ラベルには固定height制約があってはなりません。この場合、AutoLayoutはラベルをテキストに合わせてサイズ変更しないため、Edge制約の設定はキー。 (緑色の矢印)
  2. [Subview]手順1と3は簡単に実行できますが、この手順は誤解される可能性があります。ラベルの場合と同様に、サブビューにはheight制約が設定されていてはなりません。すべてのサブビューにはtop制約が設定されている必要があり、bottom制約は無視されます。これにより、実行時に満たされない制約例外がトリガーされると思われますが、最後のサブビューにbottom制約を設定した場合はそうなりません。そうしないと、レイアウトが破壊されます。 (赤い矢印)

  3. [Superview]必要な方法ですべての制約を設定しますが、height制約に大きな注意を払ってください。ランダムな値を割り当てますが、オプションにすると、AutoLayoutはサブビューに合わせて高さを正確に設定します。 (青い矢印)

これは完全に機能し、追加のシステムレイアウト更新メソッドを呼び出す必要はありません。

4
tesla