UIScrollView内に動的な高さを持つコントローラーを使用してコンテナービューを作成し、自動レイアウトを使用して自動的にサイズ変更しようとしています。
View Controller Aはスクロールビューであり、コンテナビューと以下のコンテンツが含まれています。
View Controller Bは、動的なサイズにしたいView Controllerであり、View Controller AのScroll Viewですべてのコンテンツをフルハイトで表示します。
Aのコンテナビューのサイズを自動的に設定するためにBの動的サイズを取得する際にいくつかの問題があります。ただし、Aのコンテナビューに高さの制約を設定すると 、
View Controller Bの高さも250の場合、予想される出力になります。高さ1000でも正常に機能するため、私の知る限り、すべての自動レイアウト制約が適切に設定されています。残念ながら、実際には高さは動的である必要があるため、高さの制約をまったく設定しないようにします。
View Controller Bの設定がコンテンツに応じて自動的に更新されるように設定できるかどうか、または見逃した他のトリックがあるかどうかはわかりません。どんな助けでも大歓迎です!
高さの制約を設定せずに、View Controller Bのサイズに応じてAのContainer Viewのサイズを変更する方法はありますか?
うん、あります。私は自分のプロジェクトの1つでそのような動作を達成することができました。
Interface Builderでルートビューに設定された固定フレームを模倣する制約を追加しないようにシステムに指示するだけです。これを行う最適な場所は、埋め込みセグエがトリガーされたときのコンテナビューコントローラです。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// You might want to check if this is your embed segue here
// in case there are other segues triggered from this view controller.
segue.destinationViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
}
コンテナにロードするビューが上から下に制約されていることを確認する必要があります。垂直制約のいずれかの優先度を1000未満の値に設定する必要があります(常に下部制約を使用することをお勧めしますこれが必要です。そうしないと、Interface Builderが文句を言うので、正当な理由があります。
設計時には、ルートビューのサイズ(高さ)は固定されています。これで、すべてのサブビューの高さが固定され、すべてが同じ優先度の固定制約に接続されている場合、固定ルートビューの高さがサブビューと垂直制約の合計高さと一致しない限り、これらすべての要件を満たすことはできません。いずれかの制約の優先度を999に下げると、Interface Builderはどの制約を解除するかを認識します。ただし、実行時に-translatesAutoresizingMaskIntoConstraints
プロパティが上記のように設定されている場合、ルートビューの固定フレームはなくなり、システムは代わりに999の優先度制約を使用します。
@Mischaの答えから、これを行うコンテンツに応じてcontainerViewの高さを動的にすることができました:
ContainerViewのviewControllerに次を記述します。
override func loadView() {
super.loadView()
view.translatesAutoresizingMaskIntoConstraints = false
}
また、IBの垂直方向の制約がすべて設定されていることに注意してください。これにより、View Controllerの外部からview.translatesAutoresizingMaskIntoConstraints = falseを設定する必要はありません。
私の場合、コンテナのサイズをviewController内のtableViewに変更しようとしました。 tableViewには、そのスーパービューに応じて柔軟な高さがあるため(IBではすべて問題ありません)、これを行うことでコードの垂直方向の制約を完了しました。
@IBOutlet private var tableView: UITableView! {
didSet {
tableView.addConstraint(tableViewHeight)
}
}
private lazy var tableViewHeight: NSLayoutConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 0)
そして、tableviewのcontentSizeの高さを観察し、必要に応じてtableViewHeight制約の定数をプログラムで調整します。
Swift 4、Xcode 9
受け入れられた答えだけでは問題を解決できませんでした。
私の階層:ScrollView->コンテンツビュー(UIView)->ビュー|コンテナビュー|その他のビュー。
ScrollViewとContainerの両方を動的に調整するには、次の制約を追加する必要がありました。
view.translatesAutoresizingMaskIntoConstraints = false
をprepareForSegue()
またはloadView()
に設定します。他の回答が述べられています。これで、自動サイズ変更スクロールビュー内に動的に調整可能なコンテナビューができました。
この問題に対する@Mischaの優れたソリューションに基づいて、コンテナが動的にサイズ設定されたUITableViewを埋め込む場合、contentSizeおよび intrinsicContentSize をオーバーライドすること、およびtranslatesAutoresizingMaskIntoConstraints = false
を受け入れられた答え。
親ビューがコンテナービューを読み込んで設定すると、各UITableViewCellsの固有の高さは0であると推測されるため、次のUITableViewDelegateメソッドは:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
呼び出されません。これにより、UITableViewはコンテンツがないように見えます。
固有のコンテンツサイズをオーバーライドして実際のコンテンツサイズを返すということは、テーブルビューがコンテンツに必要なサイズで表示されることを意味します。
EmilioPeláezによる素晴らしい 記事 は、このトピックについてより深く掘り下げています。