web-dev-qa-db-ja.com

UITableViewのcontentSizeはいつ設定されますか?

UITableViewに非スクロールUIScrollViewがあります。 UITableViewのフレームサイズをコンテンツサイズに設定します。

UITableViewに行を追加すると、insertRowsAtIndexPaths:withRowAnimationUITableViewに。次に、UITableViewのフレームのサイズを変更するメソッドを呼び出します。

- (void)resizeTableViewFrameHeight
{
    // Table view does not scroll, so its frame height should be equal to its contentSize height
    CGRect frame = self.tableView.frame;
    frame.size = self.tableView.contentSize;
    self.tableView.frame = frame;
}

ただし、contentSizeはこの時点では更新されていないようです。行とセクションの数に基づいて上記の方法でフレームを手動で計算すると、この方法は適切に機能します。

私の質問は、UITableViewを取得してそのcontentSizeを更新するにはどうすればよいですか?私はreloadDataを呼び出すことができたと思いますが、それはおそらくそれを行うでしょうが、1つのセルを挿入しているときにテーブル全体をリロードするのは効率が悪いようです。

44
Darren

UITableViewでlayoutIfNeededを呼び出すことにより、UITableViewにコンテンツのサイズを強制的に計算させることができます。

可変サイズのコンテナビューにあるUITableViewControllerサブクラスの例:

- (CGSize)preferredContentSize
{
    // Force the table view to calculate its height
    [self.tableView layoutIfNeeded];
    return self.tableView.contentSize;
}

2016-07-28更新これはテストされていないSwift=同じことの例です。動作するはずですが、コメントを残さない場合は、コメントを残してください。残念ながら私はSwiftにあまり詳しくありません。

override var preferredContentSize: CGSize {
    get {
        self.tableView.layoutIfNeeded()
        return self.tableView.contentSize
    }
    set {}
}
71
felinira

KVO(Key-Value Observing)は好きではありませんが、テーブルのcontentSizeがいつ変更されたかを正確に知るためのかなり良い方法です(ランダムな場所でupdateメソッドを呼び出すのではなく)。使用するのはかなり簡単です(やや不可解で暗黙的です)。テーブルのcontentSizeの変更を確認するには、次の手順を実行します。

1)テーブルのcontentSizeプロパティのオブザーバーになります:

[self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:NULL];

これは通常、tableViewを保持するView Controllerで行われます(viewDidLoad:、 例えば)。

2)KVO監視方法を実装し、必要な変更を加えます。

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if(object == self.tableView && [keyPath isEqualToString:@"contentSize"]) {
        // perform your updates here
    }
}

3)ある論理ポイントでオブザーバーとしてView Controllerを削除します(deallocで呼び出します)。あなたはこれを次のように行います:

- (void)dealloc {
    [self.tableView removeObserver:self forKeyPath:@"contentSize"];
}
25
Brian Sachetta

これを試して:

- (void)resizeTableViewFrameHeight
{
    UITableView *tableView = self.tableView;
    CGRect frame = tableView.frame;
    frame.size.height = [tableView sizeThatFits:CGSizeMake(frame.size.width, HUGE_VALF)].height;
    tableView.frame = frame;
}
14
rob mayoff
  1. オブザーバーを追加します(私のサンプルではviewDidLoad

    tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
    
  2. 価値を観察する

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if let obj = object as? UITableView {
            if obj == self.tableView && keyPath == "contentSize" {
                if let newSize = change?[NSKeyValueChangeKey.newKey] as? CGSize {
                    //do stuff here
                }
            }
        }
    }
    
  3. 不要なオブザーバーを削除する

    deinit {
        self.tableView.removeObserver(self, forKeyPath: "contentSize")
    }
    
7
gbk

@Farthenが示唆したように、常にyourTableView.layoutIfNeeded()を呼び出して、最初にコンテンツサイズを再計算する必要があります。

LayoutIfNeededを呼び出すと、UITableViewはcontentSizeを再度計算し、フレームまたは定数を更新できます。

簡単な2行のコードで、より多くの労力を節約できます。

tableView.layoutIfNeeded()
tableViewHeight.constant = tableView.contentSize.height
3
Anil Kukadeja

フッターのフレームを変更できます。フッターのアニメーション表示の前に呼び出します。

if self.newTableView.contentSize.height < self.newTableView.frame.height {
        let additionalHeight: CGFloat = self.newTableView.frame.height - self.newTableView.contentSize.height

        let tableFooterView = self.newTableView.tableFooterView!

        let x = tableFooterView.frame.Origin.x
        let y = tableFooterView.frame.Origin.y + additionalHeight
        let width = tableFooterView.frame.width
        let height = tableFooterView.frame.height

        tableFooterView.frame = CGRect(x: x, y: y, width: width, height: height)
    }
0

行の追加/削除後に適切なサイズを取得するTableViewの問題に対処するときに、これは私にとってはうまくいきました

を使用して

    tableView.layoutIfNeeded()

そして設定

    tableView.estimatedRowHeight = UITableViewAutomaticDimension
0
RiceAndBytes