UITableView
に非スクロールUIScrollView
があります。 UITableView
のフレームサイズをコンテンツサイズに設定します。
UITableView
に行を追加すると、insertRowsAtIndexPaths:withRowAnimation
:UITableView
に。次に、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つのセルを挿入しているときにテーブル全体をリロードするのは効率が悪いようです。
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 {}
}
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"];
}
これを試して:
- (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;
}
オブザーバーを追加します(私のサンプルではviewDidLoad
tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
価値を観察する
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
}
}
}
}
不要なオブザーバーを削除する
deinit {
self.tableView.removeObserver(self, forKeyPath: "contentSize")
}
@Farthenが示唆したように、常にyourTableView.layoutIfNeeded()を呼び出して、最初にコンテンツサイズを再計算する必要があります。
LayoutIfNeededを呼び出すと、UITableViewはcontentSizeを再度計算し、フレームまたは定数を更新できます。
簡単な2行のコードで、より多くの労力を節約できます。
tableView.layoutIfNeeded()
tableViewHeight.constant = tableView.contentSize.height
フッターのフレームを変更できます。フッターのアニメーション表示の前に呼び出します。
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)
}
行の追加/削除後に適切なサイズを取得するTableViewの問題に対処するときに、これは私にとってはうまくいきました
を使用して
tableView.layoutIfNeeded()
そして設定
tableView.estimatedRowHeight = UITableViewAutomaticDimension