-
-
Save alexmx/3bd217b25542fc3dd41fa79cfe2a22c7 to your computer and use it in GitHub Desktop.
Edited @Heidan34's comment to take into account Safe Area insets:
func adjustFooterViewHeightToFillTableView() {
// Invoke from UITableViewController.viewDidLayoutSubviews()
guard let tableFooterView = self.tableFooterView else { return }
let minHeight = tableFooterView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
let currentFooterHeight = tableFooterView.frame.height
let safeAreaBottomHeight = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0.0
let fitHeight = self.frame.height - self.adjustedContentInset.top - self.contentSize.height + currentFooterHeight - safeAreaBottomHeight
let nextHeight = (fitHeight > minHeight) ? fitHeight : minHeight
// No height change needed ?
guard round(nextHeight) != round(currentFooterHeight) else { return }
var frame = tableFooterView.frame
frame.size.height = nextHeight
tableFooterView.frame = frame
self.tableFooterView = tableFooterView
}
Prior solutions were additive to the footer height when viewDidLayoutSubviews is called multiple times, causing the footer to become larger than intended. Maybe it worked fine in a UITableView subclass/extension, but not in a UITableViewController (my usage).
Here's the updated logic applied directly in a UITableViewController context:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Fill any empty content space with the footer view, pushing it to the bottom of the screen.
fillContentGap:
if let tableFooterView = tableView.tableFooterView {
/// The expected height for the footer under autolayout.
let footerHeight = tableFooterView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
/// The amount of empty space to fill with the footer view.
let gapHeight: CGFloat = tableView.bounds.height - tableView.adjustedContentInset.top - tableView.adjustedContentInset.bottom - tableView.contentSize.height
// Ensure there is space to be filled
guard gapHeight.rounded() > 0 else { break fillContentGap }
// Fill the gap
tableFooterView.frame.size.height = gapHeight + footerHeight
}
}
Of course, make sure your constraints on your footer content are sufficient to keep it pinned to the view's bottom edge as its height expands.
It's also worth noting that the Swift compiler has a time with the lengthy gapHeight
calculation, which is why I explicitly declared its type. In my usage I have an extension var vertical: CGFloat { top + bottom }
on UIEdgeInsets which helps reduce this line a bit more.
Thank you !!! That's a very nice way to achieve a behavior I needed. I made a few changes so it can be more SwiftLint compliant :