Signal-iOS/SignalUI/ViewControllers/OWSTableSheetViewController.swift
Max Radermacher c6e0df5607
Fix initial height of table view sheets
When computing the height constraints, the table view wasn’t always
sized properly, which resulted in the wrong initial height.
2022-07-27 15:31:23 -07:00

84 lines
3.1 KiB
Swift

//
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
//
import Foundation
import UIKit
open class OWSTableSheetViewController: InteractiveSheetViewController {
public let tableViewController = OWSTableViewController2()
public override var interactiveScrollViews: [UIScrollView] { [tableViewController.tableView] }
public override var sheetBackgroundColor: UIColor {
OWSTableViewController2.tableBackgroundColor(isUsingPresentedStyle: true)
}
private var contentSizeHeight: CGFloat {
let tableView = tableViewController.tableView
// The `adjustedContentInset` property diverges from its stable value during
// interactive dismiss operations. This causes weird drag/height jump behavior.
// Instead, compute the height using `view.safeAreaInsets`, which remains stable
// during animations. (Note that `.top` isn't considered here since
// `maximumHeight` prevents the view's height from extending into top safe area.)
return tableView.contentSize.height + tableView.contentInset.totalHeight + view.safeAreaInsets.bottom
}
public override var minimizedHeight: CGFloat {
return min(contentSizeHeight, maximizedHeight)
}
public override var maximizedHeight: CGFloat {
min(contentSizeHeight, CurrentAppContext().frame.height - (view.safeAreaInsets.top + 32))
}
public required init() {
super.init()
tableViewController.shouldDeferInitialLoad = false
}
public override func viewDidLoad() {
super.viewDidLoad()
addChild(tableViewController)
contentView.addSubview(tableViewController.view)
tableViewController.view.autoPinEdgesToSuperviewEdges()
updateViewState()
}
public override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
updateViewState()
}
private var previousMinimizedHeight: CGFloat?
private var previousSafeAreaInsets: UIEdgeInsets?
public func updateViewState() {
if previousSafeAreaInsets != tableViewController.view.safeAreaInsets {
updateTableContents()
previousSafeAreaInsets = tableViewController.view.safeAreaInsets
}
// The table view might not have its final size when this method is called.
// Run a layout pass so that we compute the correct height constraints.
self.tableViewController.tableView.layoutIfNeeded()
// This comparison isn't redundant: assigning same value to `heightConstraint.constant`
// triggers a layout cycle and therefore this method, where height being reset to a previous value,
// killing interactive dismiss.
let minimizedHeight = minimizedHeight
if minimizedHeight != previousMinimizedHeight {
heightConstraint.constant = minimizedHeight
previousMinimizedHeight = minimizedHeight
}
maxHeightConstraint.constant = maximizedHeight
}
public override func themeDidChange() {
super.themeDidChange()
updateTableContents()
}
open func updateTableContents(shouldReload: Bool = true) {
}
}