1. ホーム
  2. ios

[解決済み] autolayoutでtableHeaderView(UITableView)の高さを設定する方法を教えてください。

2023-04-19 04:38:17

質問

この3、4時間、壁に頭をぶつけているのですが、なかなか解決しません。私はその中にフルスクリーンのUITableViewを持つUIViewControllerを持っています(画面上にいくつかの他のものがあり、それが私がUITableViewControllerを使用できない理由です)、私はautolayoutでリサイズするテーブルHeaderViewを取得したいです。言うまでもなく、それは協力的ではありません。

以下のスクリーンショットを参照してください。

overviewLabel(例:"List overview information here."テキスト)には動的コンテンツがあるので、autolayout を使用して、それおよびそれのスーパービューのサイズを変更しています。テーブルビューの下にあるテーブルヘッダービューを除いては、すべてうまくリサイズできています。

そのヘッダービューのサイズを変更するために私が見つけた唯一の方法は、次のコードを使用して、プログラム的に行うことです。

CGRect headerFrame = self.headerView.frame;
headerFrame.size.height = headerFrameHeight;
self.headerView.frame = headerFrame;
[self.listTableView setTableHeaderView:self.headerView];

この場合、headerFrameHeightは以下のようにtableViewHeaderの高さを手動で計算することになります。 (innerHeaderViewは白い領域、または2番目の"View"、headerViewはtableHeaderView) :

CGFloat startingY = self.innerHeaderView.frame.origin.y + self.overviewLabel.frame.origin.y;
CGRect overviewSize = [self.overviewLabel.text
                       boundingRectWithSize:CGSizeMake(290.f, CGFLOAT_MAX)
                       options:NSStringDrawingUsesLineFragmentOrigin
                       attributes:@{NSFontAttributeName: self.overviewLabel.font}
                       context:nil];
CGFloat overviewHeight = overviewSize.size.height;
CGFloat overviewPadding = ([self.overviewLabel.text length] > 0) ? 10 : 0; // If there's no overviewText, eliminate the padding in the overall height.
CGFloat headerFrameHeight = ceilf(startingY + overviewHeight + overviewPadding + 21.f + 10.f);

手動計算は機能しますが、不格好で、将来的に変更された場合にエラーが発生しがちです。私ができるようにしたいのは、他のどこでもできるように、提供された制約に基づいてtableHeaderViewが自動リサイズされるようにすることです。しかし、どうしてもそれを理解することができません。

SOにこれに関するいくつかの投稿がありますが、どれも明確ではなく、結局私をさらに混乱させることになりました。以下はその一部です。

translatesAutoresizingMaskIntoConstraints プロパティを NO に変更することは、私にとってはエラーを引き起こすだけで、いずれにしても概念的には意味がありません。

どんな助けでも、本当に感謝します!

EDIT 1: TomSwiftさんのご指摘のおかげで、解決できました。overviewの高さを手動で計算するのではなく、以下のように計算してもらってから、以前のようにtableHeaderViewを設定しなおせばいいんですね。

[self.headerView setNeedsLayout];
[self.headerView layoutIfNeeded];
CGFloat height = [self.innerHeaderView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + self.innerHeaderView.frame.origin.y; // adding the origin because innerHeaderView starts partway down headerView.

CGRect headerFrame = self.headerView.frame;
headerFrame.size.height = height;
self.headerView.frame = headerFrame;
[self.listTableView setTableHeaderView:self.headerView];

2を編集します。 他の人が指摘したように、編集1で投稿された解決策はviewDidLoadで動作しないようです。しかし、それはviewWillLayoutSubviewsで動作するようです。以下にコード例を示します。

// Note 1: The variable names below don't match the variables above - this is intended to be a simplified "final" answer.
// Note 2: _headerView was previously assigned to tableViewHeader (in loadView in my case since I now do everything programatically).
// Note 3: autoLayout code can be setup programatically in updateViewConstraints.
- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    [_headerWrapper setNeedsLayout];
    [_headerWrapper layoutIfNeeded];
    CGFloat height = [_headerWrapper systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    CGRect headerFrame = _headerWrapper.frame;
    headerFrame.size.height = height;
    _headerWrapper.frame = headerFrame;
    _tableView.tableHeaderView = _headerWrapper;
}

どのように解決するのですか?

この問題を解決するには UIView systemLayoutSizeFittingSize: メソッドを使用して、ヘッダービューの最小バウンディングサイズを取得する必要があります。

このQ/Aで、このAPIの使用に関するさらなる議論を提供しています。

autolayoutですべてのサブビューに合うようにスーパービューのサイズを変更するにはどうすればよいですか?