10

私はこれにしばらく苦労してきました。これを正しい方法で行っていることを確認したいと思います。参考までに、私は Storyboards で AutoLayout を使用しています。これは iOS7 専用アプリです。

ヘッダー ビューを持つ UITableView があり、HeaderView の UI はストーリーボードに接続されています。ストーリーボードにヘッダーを残しました。ヘッダーにはいくつかの要素が含まれており、そのうちの 1 つはスクロールできない UITextView です。

ストーリーボードで基本的にどのように見えるかのスクリーンショットを次に示します。

スクリーンショット

目立つようにヘッダー ビューの背景を濃いグレーにしました。

UITextView のテキストは動的にすることができるため、テキストのサイズに応じて高さを変更する必要があります。しかし、注意が必要なのは、このテキストのサイズに応じて、テーブルのヘッダー ビューも高さを調整する必要があることです。制約を使用していくつかの異なることを試しましたが、実際には正しく機能していません (AutoLayout を無効にし、プログラムでサイズを変更しない限り、これは避けたいと思います)。

もちろん、必要最小限のコードで、これを可能な限りクリーンにしたいと考えています。テーブルビューヘッダーの使用に縛られていませんが、それとそれに含まれるテキストビューを以下の実際の詳細でスクロールしたいので、私のニーズにはうまく対応しています。しかし、これを達成するためのより簡単なアプローチ (つまり、uilabel を使用) があれば、基礎となる構造を喜んで変更します。

アプローチについて何か考えはありますか?答えを通して私の手を握ってくれる人を探しているのではありません。可能であれば、いくつかの良い出発点を主に探しています。前もって感謝します!

4

4 に答える 4

33

少し前に新しい解決策を見つけました。おそらくアニメーション用に微調整する必要があり、実験的なものですが、場合によっては問題ないので、試してみてください:

  1. UITableView に headerView を追加します。
  2. サブビューを headerView に追加します。これをラッパーと呼びましょう。
  3. ラッパーの高さをそのサブビューで調整できるようにします (自動レイアウト経由)。
  4. autolayout がレイアウトを終了したら、headerView の高さをラッパーの高さに設定します。( を参照-updateTableViewHeaderViewHeight)
  5. headerView を再設定します。( を参照-resetTableViewHeaderView)

ここにいくつかのコードがあります:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    [self updateTableViewHeaderViewHeight];
}

/**
 tableView's tableViewHeaderView contains wrapper view, which height is evaluated
 with Auto Layout. Here I use evaluated height and update tableView's
 tableViewHeaderView's frame.

 New height for tableViewHeaderView is applied not without magic, that's why 
 I call -resetTableViewHeaderView.
 And again, this doesn't work due to some internals of UITableView, 
 so -resetTableViewHeaderView call is scheduled in the main run loop.
*/
- (void)updateTableViewHeaderViewHeight
{
    // get height of the wrapper and apply it to a header
    CGRect Frame = self.tableView.tableHeaderView.frame;
    Frame.size.height = self.tableHeaderViewWrapper.frame.size.height;
    self.tableView.tableHeaderView.frame = Frame;

    // this magic applies the above changes
    // note, that if you won't schedule this call to the next run loop iteration
    // you'll get and error
    // so, I guess that's not a clean solution and could be wrapped in @try@catch block
    [self performSelector:@selector(resetTableViewHeaderView) withObject:self afterDelay:0];
}

// yeah, guess there's something special in the setter
- (void)resetTableViewHeaderView
{
    // whew, this could be animated!
    [UIView beginAnimations:@"tableHeaderView" context:nil];

        self.tableView.tableHeaderView = self.tableView.tableHeaderView;

    [UIView commitAnimations];
}

これらはすべて、最初の autolayout パスの後、シームレスに機能します。後で、ラッパーのコンテンツを変更して高さが異なるようにすると、何らかの理由で機能しなくなります (UILabel をレイアウトするには、いくつかの自動レイアウト パスなどが必要になると思います)。次の実行ループ反復でViewControllerのビューのsetNeedsLayoutをスケジュールすることでこれを解決しました。

そのためのサンプル プロジェクトを作成しました: TableHeaderView+Autolayout

于 2014-03-08T13:55:55.347 に答える
-3

上記のように、UITableView では、ヘッダーの高さは自動レイアウトではなく、

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

フッターの高さは

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section

そして最後に、セルの高さが設定されます

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

テーブルビューは、ストーリーボード、XIB ファイル、またはコードからセルをロードします。上記のメソッドを使用して、ヘッダー、フッター、およびセルのフレームのサイズを設定し、そのスペースに収まるようにビューのサイズを設定します。

自動レイアウトはこれらのサイズを変更しないことを理解することが重要です。コンテナー内のビューをレイアウトするために使用されるルールのみを処理します。

セル/ヘッダー/フッターが静的サイズを使用している場合、それは非常に簡単です。すべてのサブビューの高さをロックし、heightFor で返すのと同じサイズになるようにセルを設定するだけです。

動的なセル/ヘッダー/フッターには、もう少し作業が必要です。

基本的に、実際に作成してすべてのサブビューのサイズを調整する前に、セル/ヘッダー/フッターのサイズをテーブルビューに伝えるように求められます。

cellForRowAtIndexPath および heightForRowAtIndexPath メソッドにブレークポイントを設定することで、これをすばやくテストできます。高さが最初に呼び出されます。

動的な tableviewcell の高さの場合、一般的なトリックは、viewDidLoad で単一のセルを作成し、高さを計算するために保存することです。次に、heightForRowAtIndexPath または heightForHeaderInSection に到達したら、事前に作成されたセルを使用して、最終セルで使用する値を入力します。UILabels には sizeWithFont (iOS 7 より前) または boundingRectWithSize (iOS 7.0 以降) を使用し、UITextViews には sizeThatFits を使用します。(将来これを読む人は、それらのメソッドが新しいものに置き換えられていないことを確認してください)

したがって、必要なテキストをダミーセルに入れ、ラベルとテキストビューの高さを取得し、それらの間にスペースを追加し、完了したら最終サイズを返します。

次に、 cellForRowAtIndexPath または headerForSection で値の設定をやり直しますが、表示される実際のセルで行います。

高さの計算が自動レイアウト設定と一致する場合、すべてがそのために作られたスペースに完全に収まります。

既に描画された後にセルまたはヘッダーの高さを変更する場合は、次のようにしてテーブルビューを更新する必要があります。

[self.tableView beginUpdates];
// change the data that will cause cell height to be different in heightForCellAtIndexPath or which will change a header or footer height calculation
[self.tableView endUpdates];

これにより、テーブルビューがサイズをチェックし、変更された場合にのみセルまたはヘッダー/フッターを更新します。

于 2013-11-07T03:30:13.797 に答える
-4

テーブル ビュー ヘッダー ビューは、tableView:viewForHeaderInSection: デリゲート メソッドを介してテーブル ビューに与えられます。

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    // create your header view here (read the docs on this method, there are some specific requirements)...

}

ストーリーボードでヘッダー ビューをデザインできるかどうかはわかりません。個々の XIB ファイルを使用するか、プログラムで行う必要があると思います。

つまり、テーブル ビュー ヘッダー ビューを提供する必要がある場合は、コードで制約を作成する方向に向かっていると思います。

一方、テーブルビューのヘッダービューは本当に必要ないかもしれません。たぶん、あなたが求めているのは、ユーザーがテーブルをスクロールしても動かない、テーブルビューの上のサブビューだけです。そのためには、IB でビュー階層を作り直す必要があります。現在、いわゆるヘッダー ビューはテーブル ビュー内にあります。あなたはそれを望んでいません。

または、静的セルを使用しているように見えるので、上部の静的セルをいわゆるヘッダー ビューの外観にすることができます。

于 2013-10-17T23:48:02.463 に答える